<?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>Nivedita Bhadra</title>
<link>https://bntechie.github.io/tutorials/</link>
<atom:link href="https://bntechie.github.io/tutorials/index.xml" rel="self" type="application/rss+xml"/>
<description>Senior Computational Scientist — statistical genetics, computational modeling, and simulation.</description>
<generator>quarto-1.9.38</generator>
<lastBuildDate>Wed, 05 Aug 2026 21:00:00 GMT</lastBuildDate>
<item>
  <title>Large Language Models and Working with LLM APIs</title>
  <dc:creator>Nivedita </dc:creator>
  <link>https://bntechie.github.io/tutorials/LLM_API/llm-api-tutorial.html</link>
  <description><![CDATA[ 




<section id="introduction" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="introduction"><span class="header-section-number">1</span> Introduction</h2>
<p>A language model is a system that estimates how likely a given sequence of words is, and uses that estimate to predict what comes next. Given “I am going to the”, a language model doesn’t retrieve a stored answer — it assigns a probability to every candidate next word based on patterns learned from text, and the most likely candidates (<code>store</code>, <code>gym</code>, <code>office</code>) reflect what tends to follow that phrase in the data it learned from.</p>
<p>A Large Language Model (LLM) is the same idea at a much larger scale: a neural network, almost always built on the Transformer architecture, trained on a very large text corpus to perform this next-token prediction task, and then adapted so that the resulting model can follow instructions and hold a conversation rather than just continue text.</p>
<p>This notebook builds that idea computationally — training a small next-token prediction model from scratch, verifying it reproduces the “going to the ___” example directly rather than asserting it — and then works through what an LLM API actually is, building a working (if self-contained) API client that demonstrates authentication, request structure, token accounting, and rate limiting. Where real hosted models are involved, this notebook uses the current OpenAI and Google Gen AI SDKs to verify their setup code is correct and importable, since no network access to those providers’ endpoints is available in this environment; the toy API built below is what handles the actual executed generation examples.</p>
</section>
<section id="next-token-prediction-built-from-scratch" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="next-token-prediction-built-from-scratch"><span class="header-section-number">2</span> Next-Token Prediction, Built From Scratch</h2>
<p>The mechanism underlying every LLM can be demonstrated with a tiny model trained on a handful of sentences. A bigram model — predicting the next word from only the single word before it — is a drastic simplification of what a real Transformer does (which conditions on the entire preceding context, not just one word), but the underlying operation is the same: count how often each word follows a given word in training data, and turn those counts into a probability distribution over what comes next.</p>
<div id="1b961041" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> re</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> defaultdict, Counter</span>
<span id="cb1-3"><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="cb1-4"></span>
<span id="cb1-5">training_sentences <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb1-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i am going to the store"</span>,</span>
<span id="cb1-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i am going to the gym"</span>,</span>
<span id="cb1-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i am going to the gym"</span>,</span>
<span id="cb1-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i am going to the office"</span>,</span>
<span id="cb1-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i love eating pizza"</span>,</span>
<span id="cb1-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i love eating salad"</span>,</span>
<span id="cb1-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"the capital of france is paris"</span>,</span>
<span id="cb1-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"she is going to the gym today"</span>,</span>
<span id="cb1-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"he loves eating pizza for dinner"</span>,</span>
<span id="cb1-15">]</span>
<span id="cb1-16"></span>
<span id="cb1-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> tokenize(text):</span>
<span id="cb1-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> re.findall(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r"</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[a-z]</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, text.lower())</span>
<span id="cb1-19"></span>
<span id="cb1-20"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> train_bigram_model(sentences):</span>
<span id="cb1-21">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> defaultdict(Counter)</span>
<span id="cb1-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> sentence <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sentences:</span>
<span id="cb1-23">        tokens <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;">"&lt;start&gt;"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> tokenize(sentence) <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;">"&lt;end&gt;"</span>]</span>
<span id="cb1-24">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> prev_tok, next_tok <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;">zip</span>(tokens, tokens[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:]):</span>
<span id="cb1-25">            model[prev_tok][next_tok] <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="cb1-26">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> model</span>
<span id="cb1-27"></span>
<span id="cb1-28">bigram_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_bigram_model(training_sentences)</span>
<span id="cb1-29"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Learned continuations of 'the':"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(bigram_model[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"the"</span>]))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Learned continuations of 'the': {'store': 1, 'gym': 3, 'office': 1, 'capital': 1}</code></pre>
</div>
</div>
<p>The raw counts are converted to a probability distribution the same way a real model’s output logits are: via softmax, with a temperature parameter controlling how sharply the distribution favors the highest-count option.</p>
<div id="f05b4a1c" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> next_token_probabilities(model, prev_token, temperature<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>
<span id="cb3-2">    counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model[prev_token]</span>
<span id="cb3-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> counts:</span>
<span id="cb3-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {}</span>
<span id="cb3-5">    tokens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(counts.keys())</span>
<span id="cb3-6">    logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.log(np.array(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(counts.values()), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>))</span>
<span id="cb3-7">    scaled <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> temperature</span>
<span id="cb3-8">    exp_scaled <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.exp(scaled <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> scaled.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>())</span>
<span id="cb3-9">    probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> exp_scaled <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> exp_scaled.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span>
<span id="cb3-10">    <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;">dict</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(tokens, probs))</span>
<span id="cb3-11"></span>
<span id="cb3-12">probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> next_token_probabilities(bigram_model, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"the"</span>, temperature<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>
<span id="cb3-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> token, p <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;">sorted</span>(probs.items(), key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>x[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]):</span>
<span id="cb3-14">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>token<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:10s}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><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;">:.1%}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>gym        50.0%
store      16.7%
office     16.7%
capital    16.7%</code></pre>
</div>
</div>
<p>This reproduces the classic “I am going to the ___” example exactly: <code>gym</code> is the most probable continuation given the training data, followed by <code>store</code>, <code>office</code>, and <code>capital</code> at equal lower probability, matching how often each followed “the” during training rather than being asserted.</p>
<div id="51cba8ae-44f3-4b0d-aa8e-051962b5806e" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#pip install matplotlib numpy gradio openai google-genai</span></span></code></pre></div></div>
</div>
<div id="c45514d5" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb6-2"></span>
<span id="cb6-3">tokens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(probs.keys())</span>
<span id="cb6-4">values <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(probs.values())</span>
<span id="cb6-5"></span>
<span id="cb6-6">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<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;">6</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.5</span>))</span>
<span id="cb6-7">bars <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ax.bar(tokens, values, color<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;">"#4C72B0"</span>)</span>
<span id="cb6-8">ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted probability"</span>)</span>
<span id="cb6-9">ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Next-token prediction after "I am going to the ___"'</span>)</span>
<span id="cb6-10">ax.set_ylim(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(values) <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.3</span>)</span>
<span id="cb6-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> bar, p <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;">zip</span>(bars, values):</span>
<span id="cb6-12">    ax.text(bar.get_x() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> bar.get_width() <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>, p <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.01</span>, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><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;">:.0%}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, ha<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;">"center"</span>)</span>
<span id="cb6-13">plt.tight_layout()</span>
<span id="cb6-14">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>Fontconfig warning: ignoring UTF-8: not a valid region tag
Matplotlib is building the font cache; this may take a moment.</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/LLM_API/llm-api-tutorial_files/figure-html/cell-5-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="the-evolution-of-language-modeling-architectures" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="the-evolution-of-language-modeling-architectures"><span class="header-section-number">3</span> The Evolution of Language Modeling Architectures</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Description</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>N-gram models</td>
<td>Predict the next token from a fixed-size window of preceding tokens (e.g., the single previous word, as in the bigram model above)</td>
<td>Trigram models</td>
</tr>
<tr class="even">
<td>RNN / LSTM</td>
<td>Sequence models that carry a hidden state forward, giving them memory of earlier context beyond a fixed window</td>
<td>LSTM-based language models</td>
</tr>
<tr class="odd">
<td>Transformers</td>
<td>Process an entire sequence in parallel via self-attention, allowing every token to condition on every other token directly rather than through a chain of hidden states</td>
<td>BERT, the GPT family</td>
</tr>
</tbody>
</table>
<p>The bigram model above sits at the first row of this table — real LLMs use the third. The practical consequence of the shift to Transformers is that context is no longer bottlenecked through a single fixed-size window or a sequentially-updated hidden state, which is part of why modern models can condition coherently on very long inputs.</p>
</section>
<section id="what-makes-a-model-large" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="what-makes-a-model-large"><span class="header-section-number">4</span> What Makes a Model “Large”</h2>
<p>Three factors are usually meant by “large”:</p>
<ul>
<li><strong>Parameters</strong> — the learned weights in the network. Early GPT-generation models were in the tens to low hundreds of billions of parameters; current frontier models use architectures (commonly mixture-of-experts) where only a fraction of total parameters activate per token, so raw parameter count alone is no longer a reliable proxy for capability across model families.</li>
<li><strong>Context window</strong> — how many tokens the model can condition on in a single request. This has grown substantially: from roughly 2K–8K tokens in early GPT-3-era models to context windows in the hundreds of thousands to millions of tokens in current frontier models.</li>
<li><strong>Training corpus</strong> — the scale of text (and increasingly code, images, and other modalities) the model was trained on, now typically measured in trillions of tokens.</li>
</ul>
</section>
<section id="how-an-llm-is-built-three-phases" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="how-an-llm-is-built-three-phases"><span class="header-section-number">5</span> How an LLM Is Built: Three Phases</h2>
<p><strong>Training (pretraining).</strong> The model repeatedly predicts a masked or next token across a massive unlabeled corpus, adjusting its parameters whenever its prediction is wrong — mechanically the same process demonstrated with the toy bigram model above, just at a vastly larger scale and with a Transformer architecture instead of bigram counts.</p>
<p><strong>Fine-tuning.</strong> A pretrained model is further trained on a smaller, curated dataset to specialize its behavior — for instruction-following and conversational behavior in general-purpose assistants, or for a narrower domain such as legal or medical text.</p>
<p><strong>Inference.</strong> The trained model is used to generate output for new prompts, with no further weight updates. This is what happens every time a request is sent to a model through an API — which is the subject of the rest of this notebook.</p>
</section>
<section id="why-llms-matter-in-practice" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="why-llms-matter-in-practice"><span class="header-section-number">6</span> Why LLMs Matter in Practice</h2>
<p>LLMs are foundation models underlying a wide range of applications: text generation and summarization, translation, question answering over documents, conversational assistants, and code generation and explanation. Their practical value comes from being general-purpose — the same underlying model handles translation, drafting, and code review without separate task-specific training — which is what makes API access to a single model useful across many different applications rather than needing a different specialized model per task.</p>
</section>
<section id="the-current-llm-landscape" class="level2" data-number="7">
<h2 data-number="7" class="anchored" data-anchor-id="the-current-llm-landscape"><span class="header-section-number">7</span> The Current LLM Landscape</h2>
<p>Model names and version numbers in this space turn over quickly — training material describing “the current GPT model” or “the current Gemini model” from even a year or two earlier is a common source of outdated code, since API calls reference a specific model name that may since have been retired. As of mid-2026:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
</colgroup>
<thead>
<tr class="header">
<th>Family</th>
<th>Developer</th>
<th>Current generation</th>
<th>Notably superseded</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>GPT</td>
<td>OpenAI</td>
<td>GPT-5.x family (multiple capability tiers)</td>
<td>GPT-3, GPT-4, GPT-4o — all retired from ChatGPT by early 2026</td>
</tr>
<tr class="even">
<td>Claude</td>
<td>Anthropic</td>
<td>Sonnet, Opus, and Haiku tiers at the current generation, alongside a Mythos tier above Opus</td>
<td>Claude 1/2, Claude 3 family</td>
</tr>
<tr class="odd">
<td>Gemini</td>
<td>Google DeepMind</td>
<td>Gemini 3.x family (Pro and Flash tiers)</td>
<td>Gemini 1.0, Gemini 1.5 — including 1.5 Flash, used throughout older tutorials on this topic</td>
</tr>
<tr class="even">
<td>Llama</td>
<td>Meta</td>
<td>Llama 4 (Scout and Maverick generally available; Behemoth remains in training)</td>
<td>Llama 1, 2, 3</td>
</tr>
<tr class="odd">
<td>DeepSeek</td>
<td>DeepSeek</td>
<td>DeepSeek V4 (Pro and Flash)</td>
<td>DeepSeek V2, V3, V3.1, V3.2, and the R1 reasoning model</td>
</tr>
</tbody>
</table>
<p>Two structural points are worth noting independent of any specific version number. First, the trend across every major lab has been toward multiple capability tiers within a generation (a fast/cheap tier and a higher-capability tier) rather than a single flagship model, so “the current GPT model” is now a family rather than one name. Second, several providers have converged on hybrid or unified reasoning behavior — a single model that can operate in a fast mode or a slower, more deliberate reasoning mode — rather than shipping reasoning as an entirely separate model line, which was still the case in the GPT-o1/o3 and DeepSeek-R1 generation.</p>
</section>
<section id="what-is-an-llm-api" class="level2" data-number="8">
<h2 data-number="8" class="anchored" data-anchor-id="what-is-an-llm-api"><span class="header-section-number">8</span> What Is an LLM API?</h2>
<p>An API (Application Programming Interface) is a defined way for one piece of software to request something from another over a network — a client sends a structured request, a server processes it and returns a structured response. An LLM API applies this pattern to a hosted language model: the request typically includes a prompt, a model name, and generation settings (temperature, maximum output length); the response includes the generated text along with metadata such as token counts.</p>
<p>Working with an LLM API in practice means handling four things: <strong>authentication</strong> (proving the request is authorized, via an API key), <strong>request construction</strong> (the prompt and generation parameters), <strong>the response format</strong> (extracting the generated text from a structured response object), and <strong>usage accounting</strong> (tracking tokens consumed, since most providers bill and rate-limit by token count).</p>
<p>The rest of this section builds a working — if self-contained — version of all four, since this environment has no network access to a real provider’s endpoint. The mechanics demonstrated (key checking, request/response structure, token counting, rate limiting) are exactly what a real API client handles; only the actual language generation is a toy stand-in.</p>
</section>
<section id="building-a-minimal-llm-api-end-to-end" class="level2" data-number="9">
<h2 data-number="9" class="anchored" data-anchor-id="building-a-minimal-llm-api-end-to-end"><span class="header-section-number">9</span> Building a Minimal LLM API, End to End</h2>
<p>The pieces below assemble into a single <code>call_llm_api()</code> function that behaves like a real hosted API: it checks an API key, tracks a per-key call count against a rate limit, tokenizes the prompt, generates a continuation using the bigram model trained earlier, and returns a response object with a token-usage breakdown — the same shape as a real provider’s response.</p>
<div id="9cacdc2d" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb8-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> time</span>
<span id="cb8-3"></span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- a minimal "account" store, standing in for a real provider's auth system ---</span></span>
<span id="cb8-5">VALID_API_KEYS <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;">"demo-key-abc123"</span>}</span>
<span id="cb8-6">_call_log <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> defaultdict(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>)</span>
<span id="cb8-7">RATE_LIMIT_PER_MINUTE <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;">100</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># generous default so later demo cells aren't blocked by earlier ones</span></span>
<span id="cb8-8"></span>
<span id="cb8-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> AuthenticationError(<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">Exception</span>):</span>
<span id="cb8-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">pass</span></span>
<span id="cb8-11"></span>
<span id="cb8-12"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> RateLimitError(<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">Exception</span>):</span>
<span id="cb8-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">pass</span></span>
<span id="cb8-14"></span>
<span id="cb8-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _check_rate_limit(api_key):</span>
<span id="cb8-16">    now <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> time.time()</span>
<span id="cb8-17">    _call_log[api_key] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [t <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> _call_log[api_key] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> now <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>]</span>
<span id="cb8-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(_call_log[api_key]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> RATE_LIMIT_PER_MINUTE:</span>
<span id="cb8-19">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> RateLimitError(</span>
<span id="cb8-20">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Rate limit exceeded: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>RATE_LIMIT_PER_MINUTE<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;"> calls per minute for this key."</span></span>
<span id="cb8-21">        )</span>
<span id="cb8-22">    _call_log[api_key].append(now)</span>
<span id="cb8-23"></span>
<span id="cb8-24"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _last_known_token(tokens, model):</span>
<span id="cb8-25">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Walk backward through the prompt's tokens to find the most recent one</span></span>
<span id="cb8-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    the model actually saw during training; falls back to &lt;start&gt; if none did."""</span></span>
<span id="cb8-27">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tok <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;">reversed</span>(tokens):</span>
<span id="cb8-28">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> tok <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model:</span>
<span id="cb8-29">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> tok</span>
<span id="cb8-30">    <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;">"&lt;start&gt;"</span></span>
<span id="cb8-31"></span>
<span id="cb8-32"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _generate(prompt, max_tokens, temperature, seed):</span>
<span id="cb8-33">    rng <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random.Random(seed)</span>
<span id="cb8-34">    tokens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tokenize(prompt)</span>
<span id="cb8-35">    current <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> _last_known_token(tokens, bigram_model)</span>
<span id="cb8-36">    generated <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb8-37">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <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>(max_tokens):</span>
<span id="cb8-38">        probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> next_token_probabilities(bigram_model, current, temperature<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>temperature)</span>
<span id="cb8-39">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> probs <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;end&gt;"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> probs <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> rng.random() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> probs.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;end&gt;"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>):</span>
<span id="cb8-40">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span></span>
<span id="cb8-41">        candidates, weights <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>probs.items())</span>
<span id="cb8-42">        next_tok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.choices(candidates, weights<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>weights, k<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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb8-43">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> next_tok <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;">"&lt;end&gt;"</span>:</span>
<span id="cb8-44">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span></span>
<span id="cb8-45">        generated.append(next_tok)</span>
<span id="cb8-46">        current <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> next_tok</span>
<span id="cb8-47">    <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;">" "</span>.join(generated)</span>
<span id="cb8-48"></span>
<span id="cb8-49"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> call_llm_api(prompt, api_key, model<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;">"toy-llm-mini"</span>, max_tokens<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>, temperature<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.7</span>, seed<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="cb8-50">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> api_key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> VALID_API_KEYS:</span>
<span id="cb8-51">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> AuthenticationError(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Invalid API key."</span>)</span>
<span id="cb8-52">    _check_rate_limit(api_key)</span>
<span id="cb8-53"></span>
<span id="cb8-54">    prompt_tokens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(tokenize(prompt))</span>
<span id="cb8-55">    completion_text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> _generate(prompt, max_tokens, temperature, seed)</span>
<span id="cb8-56">    completion_tokens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(tokenize(completion_text))</span>
<span id="cb8-57"></span>
<span id="cb8-58">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {</span>
<span id="cb8-59">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model"</span>: model,</span>
<span id="cb8-60">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"choices"</span>: [{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span>: completion_text}],</span>
<span id="cb8-61">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"usage"</span>: {</span>
<span id="cb8-62">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"prompt_tokens"</span>: prompt_tokens,</span>
<span id="cb8-63">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"completion_tokens"</span>: completion_tokens,</span>
<span id="cb8-64">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_tokens"</span>: prompt_tokens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> completion_tokens,</span>
<span id="cb8-65">        },</span>
<span id="cb8-66">    }</span>
<span id="cb8-67"></span>
<span id="cb8-68">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> call_llm_api(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"I am going to the"</span>, api_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;">"demo-key-abc123"</span>, seed<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="cb8-69">response</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>{'model': 'toy-llm-mini',
 'choices': [{'text': 'gym today'}],
 'usage': {'prompt_tokens': 5, 'completion_tokens': 2, 'total_tokens': 7}}</code></pre>
</div>
</div>
<p>Two failure modes worth confirming actually work, since they’re central to using any real API: an invalid key should be rejected, and exceeding the rate limit should raise rather than silently succeed.</p>
<div id="b93ebc36" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Invalid key</span></span>
<span id="cb10-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb10-3">    call_llm_api(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello"</span>, api_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;">"not-a-real-key"</span>)</span>
<span id="cb10-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> AuthenticationError <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb10-5">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Caught expected error:"</span>, e)</span>
<span id="cb10-6"></span>
<span id="cb10-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Rate limit: temporarily tighten the limit and use a dedicated key, so this</span></span>
<span id="cb10-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># demonstration doesn't consume the quota for "demo-key-abc123" used elsewhere</span></span>
<span id="cb10-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># in this notebook.</span></span>
<span id="cb10-10">VALID_API_KEYS.add(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"demo-key-for-rate-limit-test"</span>)</span>
<span id="cb10-11">rate_limit_test_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;">"demo-key-for-rate-limit-test"</span></span>
<span id="cb10-12"></span>
<span id="cb10-13">_original_limit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RATE_LIMIT_PER_MINUTE</span>
<span id="cb10-14">RATE_LIMIT_PER_MINUTE <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;">3</span></span>
<span id="cb10-15"><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>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>):</span>
<span id="cb10-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb10-17">        call_llm_api(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i love eating"</span>, api_key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>rate_limit_test_key, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>i)</span>
<span id="cb10-18">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Call </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;">: succeeded"</span>)</span>
<span id="cb10-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> RateLimitError <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb10-20">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Call </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;">: blocked -- </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>e<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>
<span id="cb10-21">RATE_LIMIT_PER_MINUTE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> _original_limit</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Caught expected error: Invalid API key.
Call 1: succeeded
Call 2: succeeded
Call 3: succeeded
Call 4: blocked -- Rate limit exceeded: 3 calls per minute for this key.</code></pre>
</div>
</div>
<p>Both behave as a real API would: the wrong key is rejected before any generation happens, and the fourth call within the same minute is blocked once the limit is reached, without needing to actually wait or hit a real server to demonstrate it.</p>
<section id="role-based-prompting" class="level3" data-number="9.1">
<h3 data-number="9.1" class="anchored" data-anchor-id="role-based-prompting"><span class="header-section-number">9.1</span> Role-Based Prompting</h3>
<p>A prompt that opens by assigning the model a persona or role is a common pattern for steering tone and framing. Since the toy model above only knows the handful of training sentences given to it, its output won’t reflect the requested persona the way a real LLM would — but the request/response mechanics are identical, which is what this section demonstrates.</p>
<div id="ac384e75" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> build_role_prompt(role, user_input):</span>
<span id="cb12-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"You are </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>role<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;">. User: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>user_input<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">Assistant:"</span></span>
<span id="cb12-3"></span>
<span id="cb12-4">prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_role_prompt(</span>
<span id="cb12-5">    role<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;">"a senior data scientist explaining concepts to a general audience"</span>,</span>
<span id="cb12-6">    user_input<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;">"the gym"</span></span>
<span id="cb12-7">)</span>
<span id="cb12-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Prompt sent to the API:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, prompt, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb12-9"></span>
<span id="cb12-10">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> call_llm_api(prompt, api_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;">"demo-key-abc123"</span>, max_tokens<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;">8</span>, seed<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>
<span id="cb12-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Response:"</span>, response)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Prompt sent to the API:
 You are a senior data scientist explaining concepts to a general audience. User: the gym
Assistant: 

Response: {'model': 'toy-llm-mini', 'choices': [{'text': 'today'}], 'usage': {'prompt_tokens': 16, 'completion_tokens': 1, 'total_tokens': 17}}</code></pre>
</div>
</div>
</section>
<section id="a-chatbot-loop" class="level3" data-number="9.2">
<h3 data-number="9.2" class="anchored" data-anchor-id="a-chatbot-loop"><span class="header-section-number">9.2</span> A Chatbot Loop</h3>
<p>A terminal chatbot is usually written with a blocking <code>input()</code> call inside a <code>while True:</code> loop, which works interactively but can’t run inside an executed notebook cell (there is no one there to type a response). The loop logic is identical either way; the only change here is replacing live keyboard input with a small pre-written list of turns, so the whole exchange runs and is captured in the output.</p>
<div id="7e48bd8f" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> run_chatbot(turns, api_key):</span>
<span id="cb14-2">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chatbot session started.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb14-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> user_input <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> turns:</span>
<span id="cb14-4">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"You: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>user_input<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>
<span id="cb14-5">        result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> call_llm_api(user_input, api_key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>api_key, max_tokens<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;">6</span>,</span>
<span id="cb14-6">                               seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hash</span>(user_input) <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;">1000</span>)</span>
<span id="cb14-7">        bot_text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> result[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"choices"</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;">"text"</span>]</span>
<span id="cb14-8">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Bot: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>bot_text<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb14-9">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chat ended."</span>)</span>
<span id="cb14-10"></span>
<span id="cb14-11">scripted_turns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb14-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i am going to the"</span>,</span>
<span id="cb14-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i love eating"</span>,</span>
<span id="cb14-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"the capital of france"</span>,</span>
<span id="cb14-15">]</span>
<span id="cb14-16"></span>
<span id="cb14-17">run_chatbot(scripted_turns, api_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;">"demo-key-abc123"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Chatbot session started.

You: i am going to the
Bot: office

You: i love eating
Bot: salad

You: the capital of france
Bot: is going to the gym

Chat ended.</code></pre>
</div>
</div>
</section>
</section>
<section id="setting-up-the-current-real-sdks" class="level2" data-number="10">
<h2 data-number="10" class="anchored" data-anchor-id="setting-up-the-current-real-sdks"><span class="header-section-number">10</span> Setting Up the Current Real SDKs</h2>
<p>The two client libraries below are the current, verified-importable SDKs for OpenAI and Google’s Gemini API. Constructing a client doesn’t require network access (it only stores configuration), so that step is executed directly; the actual generation call is shown immediately after as reference code, since it requires a real API key and a live network connection to the provider, neither of which this environment has.</p>
<p>One correction relative to older material on this topic: <code>google.generativeai</code> — the package used throughout many existing Gemini tutorials, including earlier versions of this one — is fully deprecated. Google archived that repository and consolidated all Gemini access into a single unified SDK, <code>google-genai</code>, imported as <code>from google import genai</code>. Code written against the old package will not receive updates and, per Google’s own deprecation notice, should be migrated.</p>
<div id="e0ee6a9b" class="cell" data-execution_count="9">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Current Gemini SDK -- client construction only, no network call</span></span>
<span id="cb16-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> google <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> genai</span>
<span id="cb16-3"></span>
<span id="cb16-4">gemini_client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> genai.Client(api_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;">"replace-with-a-real-key"</span>)</span>
<span id="cb16-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gemini client ready:"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(gemini_client).<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>)</span>
<span id="cb16-6"></span>
<span id="cb16-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The actual generation call (reference only -- requires a real key and network access):</span></span>
<span id="cb16-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb16-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># response = gemini_client.models.generate_content(</span></span>
<span id="cb16-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     model="gemini-3.5-flash",</span></span>
<span id="cb16-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     contents="Tell me a fun fact about space.",</span></span>
<span id="cb16-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># )</span></span>
<span id="cb16-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># print(response.text)</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Gemini client ready: Client</code></pre>
</div>
</div>
<div id="eba44174" class="cell" data-execution_count="10">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Current OpenAI SDK -- client construction only, no network call</span></span>
<span id="cb18-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> openai <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> OpenAI</span>
<span id="cb18-3"></span>
<span id="cb18-4">openai_client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> OpenAI(api_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;">"replace-with-a-real-key"</span>)</span>
<span id="cb18-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OpenAI client ready:"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(openai_client).<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>)</span>
<span id="cb18-6"></span>
<span id="cb18-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The actual generation call (reference only -- requires a real key and network access):</span></span>
<span id="cb18-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb18-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># response = openai_client.chat.completions.create(</span></span>
<span id="cb18-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     model="gpt-5.6-terra",</span></span>
<span id="cb18-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     messages=[{"role": "user", "content": "Tell me a fun fact about space."}],</span></span>
<span id="cb18-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># )</span></span>
<span id="cb18-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># print(response.choices[0].message.content)</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>OpenAI client ready: OpenAI</code></pre>
</div>
</div>
</section>
<section id="wrapping-the-api-in-a-simple-web-interface" class="level2" data-number="11">
<h2 data-number="11" class="anchored" data-anchor-id="wrapping-the-api-in-a-simple-web-interface"><span class="header-section-number">11</span> Wrapping the API in a Simple Web Interface</h2>
<p>Gradio turns a Python function into a browser-based UI with minimal code. <code>gr.Interface</code> can be constructed and inspected without calling <code>.launch()</code> — launching starts a live local server, which isn’t appropriate inside an executed notebook cell, but constructing the interface and calling its underlying function directly confirms the wiring is correct.</p>
<div id="e42e36b1" class="cell" data-execution_count="11">
<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="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> gradio <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> gr</span>
<span id="cb20-2"></span>
<span id="cb20-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> chatbot_interface(user_input):</span>
<span id="cb20-4">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> call_llm_api(user_input, api_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;">"demo-key-abc123"</span>, max_tokens<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;">8</span>,</span>
<span id="cb20-5">                           seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hash</span>(user_input) <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;">1000</span>)</span>
<span id="cb20-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"choices"</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;">"text"</span>]</span>
<span id="cb20-7"></span>
<span id="cb20-8">iface <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> gr.Interface(</span>
<span id="cb20-9">    fn<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>chatbot_interface,</span>
<span id="cb20-10">    inputs<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;">"text"</span>,</span>
<span id="cb20-11">    outputs<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;">"text"</span>,</span>
<span id="cb20-12">    title<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;">"Toy LLM API Chatbot"</span>,</span>
<span id="cb20-13">    description<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;">"Type a prompt; the response comes from the toy bigram model built earlier."</span>,</span>
<span id="cb20-14">)</span>
<span id="cb20-15"></span>
<span id="cb20-16"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Interface constructed:"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(iface).<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>)</span>
<span id="cb20-17"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Direct call through the interface function:"</span>, iface.fn(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i am going to the"</span>))</span>
<span id="cb20-18"></span>
<span id="cb20-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># To actually serve this in a browser: iface.launch()</span></span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>/opt/homebrew/Cellar/jupyterlab/4.6.1/libexec/lib/python3.14/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm</code></pre>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Interface constructed: Interface
Direct call through the interface function: office</code></pre>
</div>
</div>
</section>
<section id="best-practices" class="level2" data-number="12">
<h2 data-number="12" class="anchored" data-anchor-id="best-practices"><span class="header-section-number">12</span> Best Practices</h2>
<ul>
<li><strong>Never hard-code an API key in source.</strong> Load it from an environment variable or a <code>.env</code> file excluded from version control, as in the <code>python-dotenv</code> pattern.</li>
<li><strong>Handle authentication and rate-limit errors explicitly</strong>, as demonstrated above — a production integration should catch these rather than let the whole application crash on a transient limit.</li>
<li><strong>Track token usage from the response object</strong>, not by estimating it — the <code>usage</code> field in a real response is the authoritative count for billing and context-window purposes.</li>
<li><strong>Pin a specific model version</strong> rather than an alias that silently repoints to a newer model, if reproducible behavior matters for your use case.</li>
<li><strong>Separate the model-calling code from the UI layer</strong>, as done here (the <code>call_llm_api()</code> function is identical whether it’s called directly, from a scripted loop, or from the Gradio interface).</li>
<li><strong>Verify current model names before deploying</strong>, given how quickly they change — this notebook’s own landscape table will itself be out of date within a year or so.</li>
</ul>
</section>
<section id="limitations" class="level2" data-number="13">
<h2 data-number="13" class="anchored" data-anchor-id="limitations"><span class="header-section-number">13</span> Limitations</h2>
<ul>
<li><strong>Hallucination.</strong> A model can generate fluent, confident, and factually wrong output; this is a property of how generation works, not a bug specific to any one provider.</li>
<li><strong>No persistent memory by default.</strong> Each API call is stateless unless the calling application resends prior context, exactly as demonstrated by the fact that <code>call_llm_api()</code> above has no memory of previous calls on its own.</li>
<li><strong>No grounded understanding.</strong> A language model manipulates learned statistical patterns over tokens; it does not have verified knowledge of facts in the way a lookup against a trusted database would.</li>
<li><strong>Context window limits.</strong> Very long conversations or documents can exceed what a model can attend to in a single request, requiring truncation, summarization, or retrieval (as covered in a companion notebook on LangChain and RAG).</li>
<li><strong>Cost and token limits.</strong> API usage is typically billed per token, and usage accounting (as built above) is necessary to keep this under control.</li>
<li><strong>Data privacy.</strong> Prompts sent to a third-party API may be logged according to that provider’s data policy — sensitive information warrants caution before inclusion in a prompt.</li>
<li><strong>Bias.</strong> A model can reproduce patterns present in its training data, including skewed or unbalanced representations of certain topics or groups.</li>
</ul>
</section>
<section id="summary" class="level2" data-number="14">
<h2 data-number="14" class="anchored" data-anchor-id="summary"><span class="header-section-number">14</span> Summary</h2>
<p>A language model estimates a probability distribution over the next token given preceding context, and an LLM is this same mechanism at large scale, built on a Transformer architecture and trained in three phases: pretraining on a large corpus, fine-tuning toward instruction-following behavior, and inference on new prompts at request time. All three were demonstrated computationally above, at small scale, with a trained bigram model standing in for a full Transformer.</p>
<p>An LLM API exposes a hosted model over a standard request/response interface, and working with one in practice comes down to four concerns: authentication, request construction, response parsing, and usage accounting — all four were built and verified directly in this notebook via a self-contained toy API, since no network access to a real provider was available. The current SDKs for both major hosted providers (OpenAI, Google’s unified <code>google-genai</code>) were verified as correctly importable and constructible, with the actual generation calls documented as reference code for use with a real API key. The model landscape itself — which specific model name to put in that call — is the part of this material most likely to go stale fastest, and was flagged as such rather than treated as a fixed fact.</p>
</section>
<section id="references" class="level2" data-number="15">
<h2 data-number="15" class="anchored" data-anchor-id="references"><span class="header-section-number">15</span> References</h2>
<ul>
<li>Vaswani et al., “Attention Is All You Need” (2017) – <a href="https://arxiv.org/abs/1706.03762">arXiv:1706.03762</a></li>
<li>Brown et al., “Language Models are Few-Shot Learners” (2020) – <a href="https://arxiv.org/abs/2005.14165">arXiv:2005.14165</a></li>
<li>Chowdhery et al., “PaLM: Scaling Language Modeling with Pathways” (2022) – <a href="https://arxiv.org/abs/2204.02311">arXiv:2204.02311</a></li>
<li>OpenAI API documentation – <a href="https://platform.openai.com/docs">platform.openai.com/docs</a></li>
<li>Google Gen AI SDK documentation – <a href="https://ai.google.dev/gemini-api/docs">ai.google.dev/gemini-api/docs</a></li>
</ul>
<blockquote class="blockquote">
<p><strong>A note on the Gemini 1.5 technical report.</strong> Earlier material on this topic points to Google’s Gemini 1.5 technical report as reference documentation. That generation has since been superseded by Gemini 3.x, and the <code>gemini-1.5-flash</code> model name used throughout older tutorials (including the walkthrough this notebook is based on) no longer reflects the current model lineup. The Gemini API documentation link above always resolves to current model information rather than a fixed historical snapshot.</p>
</blockquote>
</section>
<section id="try-it-yourself" class="level2" data-number="16">
<h2 data-number="16" class="anchored" data-anchor-id="try-it-yourself"><span class="header-section-number">16</span> Try It Yourself</h2>
<p><strong>Task 1: Call an LLM API for text generation.</strong> Using either the toy <code>call_llm_api()</code> built above, or a real provider’s SDK once you have a key, send the prompt <code>"the capital of france"</code> and inspect both the generated text and the token usage in the response.</p>
<p><strong>Task 2: Build a small prompt playground.</strong> Write a function that accepts a persona and a user message, builds a role-based prompt with <code>build_role_prompt()</code>, sends it through <code>call_llm_api()</code>, and returns the response text — then try it with two different personas on the same input and compare tone and framing (in a real model; the toy model here won’t vary by persona, since it has no notion of one).</p>
<section id="solutions" class="level3" data-number="16.1">
<h3 data-number="16.1" class="anchored" data-anchor-id="solutions"><span class="header-section-number">16.1</span> Solutions</h3>
<p><strong>Task 1</strong></p>
<div id="e18b38af" class="cell" data-execution_count="12">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1">result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> call_llm_api(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"the capital of france"</span>, api_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;">"demo-key-abc123"</span>, max_tokens<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;">6</span>, seed<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;">7</span>)</span>
<span id="cb23-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Generated text:"</span>, result[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"choices"</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;">"text"</span>])</span>
<span id="cb23-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Token usage:"</span>, result[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"usage"</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Generated text: is paris
Token usage: {'prompt_tokens': 4, 'completion_tokens': 2, 'total_tokens': 6}</code></pre>
</div>
</div>
<p>The model correctly continues toward “paris” (the only completion it ever saw following “the capital of france” during training), and the usage dictionary reports 4 prompt tokens (<code>the</code>, <code>capital</code>, <code>of</code>, <code>france</code>) plus however many completion tokens were generated — confirming the token-accounting path works end to end, not just the generation path.</p>
<p><strong>Task 2</strong></p>
<div id="3a3fbc95" class="cell" data-execution_count="13">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> prompt_playground(persona, user_message, api_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;">"demo-key-abc123"</span>, seed<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="cb25-2">    prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_role_prompt(persona, user_message)</span>
<span id="cb25-3">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> call_llm_api(prompt, api_key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>api_key, max_tokens<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;">8</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>seed)</span>
<span id="cb25-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> prompt, result[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"choices"</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;">"text"</span>]</span>
<span id="cb25-5"></span>
<span id="cb25-6">personas <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb25-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a formal technical writer"</span>,</span>
<span id="cb25-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a casual, enthusiastic tutor"</span>,</span>
<span id="cb25-9">]</span>
<span id="cb25-10"></span>
<span id="cb25-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, persona <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;">enumerate</span>(personas):</span>
<span id="cb25-12">    prompt, output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> prompt_playground(persona, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i love eating"</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>i)</span>
<span id="cb25-13">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Persona: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>persona<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>
<span id="cb25-14">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Prompt sent: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>prompt<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>
<span id="cb25-15">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Response:    </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>output<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Persona: a formal technical writer
Prompt sent: You are a formal technical writer. User: i love eating
Assistant:
Response:    salad

Persona: a casual, enthusiastic tutor
Prompt sent: You are a casual, enthusiastic tutor. User: i love eating
Assistant:
Response:    pizza for dinner
</code></pre>
</div>
</div>
<p>As expected, the toy model’s output doesn’t actually shift with persona — it has no representation of tone or formality, only bigram counts from nine training sentences — but the prompt construction and API call path is exactly what would carry a persona’s influence through to a real model’s output. Swapping <code>call_llm_api()</code> for <code>openai_client.chat.completions.create()</code> or <code>gemini_client.models.generate_content()</code> with the same <code>build_role_prompt()</code> output is the only change needed to run this against a real model.</p>


</section>
</section>

 ]]></description>
  <guid>https://bntechie.github.io/tutorials/LLM_API/llm-api-tutorial.html</guid>
  <pubDate>Wed, 05 Aug 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>t-test or ANOVA? Choosing the Right Test for Before/After Treatment Across Multiple Groups</title>
  <dc:creator>Nivedita </dc:creator>
  <link>https://bntechie.github.io/tutorials/ttest_ANOVA/t-test-vs-anova-before-after-treatment.html</link>
  <description><![CDATA[ 




<section id="introduction" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="introduction"><span class="header-section-number">1</span> Introduction</h2>
<p>A question that comes up constantly in applied statistics: there are several groups — say, three treatment arms — and each subject is measured before and after treatment. Should the comparison use a t-test or an ANOVA?</p>
<p>This question, as posed, is missing information. The correct test depends on two things simultaneously: the number of groups, and the number of time points measured within each subject. Misjudging either one produces a test that is underpowered, statistically invalid, or answering a different question than the one intended.</p>
<p>This tutorial develops the decision logic, demonstrates why naive approaches fail, and works through a complete example using a mixed-design (repeated-measures) ANOVA — the test that fits a multi-group before/after design.</p>
</section>
<section id="what-a-t-test-can-and-cannot-test" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="what-a-t-test-can-and-cannot-test"><span class="header-section-number">2</span> What a t-test Can and Cannot Test</h2>
<p>A t-test compares two means. Two variants are relevant to this design.</p>
<p>An <strong>independent-samples t-test</strong> compares two separate groups measured once each — for example, a treatment group versus a control group, both assessed after treatment. The two sets of observations arise from different subjects.</p>
<p>A <strong>paired t-test</strong> compares two measurements taken from the same subjects — for example, a biomarker measured before and after treatment within a single group. Pairing removes between-subject variability from the comparison, which increases statistical power relative to treating the two measurements as independent.</p>
<blockquote class="blockquote">
<p><strong>Q: Why can’t a single t-test handle a multi-group before/after design directly?</strong> A: Each t-test variant models exactly one source of variation — either differences between groups or differences between time points — but not both together. A before/after study with three treatment arms contains both sources of variation at once, and neither t-test variant has a mechanism for modeling their combination.</p>
</blockquote>
</section>
<section id="why-not-run-several-t-tests" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="why-not-run-several-t-tests"><span class="header-section-number">3</span> Why Not Run Several t-tests?</h2>
<p>A common workaround is to run a paired t-test separately within each group, or an independent t-test at each time point, and compare the pattern of results informally. This approach fails for two reasons.</p>
<p>First, running multiple significance tests on related data inflates the family-wise Type I error rate, since each additional test carries its own probability of a false positive. With three groups tested separately, the effective error rate across the family of tests exceeds the nominal 0.05 threshold intended for a single test.</p>
<p>Second, and more fundamentally, separate t-tests cannot test the question a multi-group before/after design is built to answer: did the treatment effect — the before-to-after change — differ across groups? A set of individual paired t-tests indicates whether each group changed on its own, but provides no formal test of whether the magnitude of change differed between groups. That comparison is the <strong>group × time interaction</strong>, and testing it requires a model that includes both factors jointly.</p>
</section>
<section id="the-mixed-design-anova" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="the-mixed-design-anova"><span class="header-section-number">4</span> The Mixed-Design ANOVA</h2>
<p>A mixed-design ANOVA (also termed a between-within ANOVA) models two factors simultaneously:</p>
<ul>
<li><strong>Time</strong> (or condition) is a within-subjects factor: before and after values come from the same subjects and are therefore correlated.</li>
<li><strong>Group</strong> is a between-subjects factor: treatment arms consist of different, independent subjects.</li>
</ul>
<p>The model partitions variance into three components: a main effect of time (whether values changed overall), a main effect of group (whether groups differ overall), and a <strong>group × time interaction</strong> (whether the magnitude of change depended on group membership).</p>
<blockquote class="blockquote">
<p><strong>Q: Which of these three effects answers the original research question?</strong> A: In a treatment-comparison study, the interaction term is typically the effect of interest. A significant interaction indicates that groups did not all change by the same amount, which is the statistical signature of a treatment effect that differs from whatever change occurred in the comparison arms.</p>
</blockquote>
</section>
<section id="decision-guide" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="decision-guide"><span class="header-section-number">5</span> Decision Guide</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Design</th>
<th>Test</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Two groups, one time point</td>
<td>Independent-samples t-test</td>
</tr>
<tr class="even">
<td>One group, two time points</td>
<td>Paired t-test</td>
</tr>
<tr class="odd">
<td>Two groups, two time points (before/after)</td>
<td>Mixed ANOVA, or a t-test on change scores</td>
</tr>
<tr class="even">
<td>More than two groups, two time points</td>
<td>Mixed ANOVA</td>
</tr>
<tr class="odd">
<td>More than two time points, with or without multiple groups</td>
<td>Repeated-measures or mixed ANOVA</td>
</tr>
</tbody>
</table>
</section>
<section id="worked-example-a-biomarker-across-three-groups" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="worked-example-a-biomarker-across-three-groups"><span class="header-section-number">6</span> Worked Example: A Biomarker Across Three Groups</h2>
<p>Consider three groups — A, B, and C — with a biomarker recorded for each subject under two conditions: control and treatment. This is a 3 × 2 mixed design: group is between-subjects, condition is within-subjects, since each subject contributes both a control and a treatment value.</p>
<p>The simulation below generates 15 subjects per group, with the treatment effect itself set to differ by group: group A shows a minimal response, group B a moderate response, and group C a strong response. This is the pattern a mixed ANOVA is designed to detect via the group × condition interaction.</p>
<div id="0e91d3a0" class="cell" data-execution_count="1">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb1-2">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;">15</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># subjects per group</span></span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulate a biomarker with a group-specific baseline and a group-specific</span></span>
<span id="cb1-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># treatment response (this is what creates a group x condition interaction)</span></span>
<span id="cb1-6">simulate_group <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>(group_id, baseline, effect) {</span>
<span id="cb1-7">  subject   <span class="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>(group_id, <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;">seq_len</span>(n_per_group))</span>
<span id="cb1-8">  control   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_per_group, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</span> baseline, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb1-9">  treatment <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> control <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;">rnorm</span>(n_per_group, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</span> effect, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb1-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb1-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">subject   =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(subject, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb1-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group     =</span> group_id,</span>
<span id="cb1-13">    <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>(<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;">"control"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n_per_group),</span>
<span id="cb1-14">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">biomarker =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(control, treatment)</span>
<span id="cb1-15">  )</span>
<span id="cb1-16">}</span>
<span id="cb1-17"></span>
<span id="cb1-18">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;">rbind</span>(</span>
<span id="cb1-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_group</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;">baseline =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">effect =</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;"># minimal response</span></span>
<span id="cb1-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_group</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;">baseline =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">effect =</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;"># moderate response</span></span>
<span id="cb1-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_group</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"C"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">baseline =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">effect =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># strong response</span></span>
<span id="cb1-22">)</span>
<span id="cb1-23"></span>
<span id="cb1-24">df<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>(df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group)</span>
<span id="cb1-25">df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>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>(df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>condition, <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;">"control"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment"</span>))</span>
<span id="cb1-26">df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>subject   <span class="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>(df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>subject)</span>
<span id="cb1-27"></span>
<span id="cb1-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(df, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 4</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">subject</th>
<th data-quarto-table-cell-role="th" scope="col">group</th>
<th data-quarto-table-cell-role="th" scope="col">condition</th>
<th data-quarto-table-cell-role="th" scope="col">biomarker</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;fct&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;fct&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;fct&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>A_1</td>
<td>A</td>
<td>control</td>
<td>56.85479</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>A_2</td>
<td>A</td>
<td>control</td>
<td>47.17651</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>A_3</td>
<td>A</td>
<td>control</td>
<td>51.81564</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>A_4</td>
<td>A</td>
<td>control</td>
<td>53.16431</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>A_5</td>
<td>A</td>
<td>control</td>
<td>52.02134</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>A_6</td>
<td>A</td>
<td>control</td>
<td>49.46938</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="fa44556d" class="cell" data-execution_count="2">
<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"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aggregate</span>(biomarker <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> condition, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> df, mean)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 3</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">group</th>
<th data-quarto-table-cell-role="th" scope="col">condition</th>
<th data-quarto-table-cell-role="th" scope="col">biomarker</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;fct&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;fct&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>A</td>
<td>control</td>
<td>52.42117</td>
</tr>
<tr class="even">
<td>B</td>
<td>control</td>
<td>48.28969</td>
</tr>
<tr class="odd">
<td>C</td>
<td>control</td>
<td>51.12821</td>
</tr>
<tr class="even">
<td>A</td>
<td>treatment</td>
<td>53.37999</td>
</tr>
<tr class="odd">
<td>B</td>
<td>treatment</td>
<td>56.58443</td>
</tr>
<tr class="even">
<td>C</td>
<td>treatment</td>
<td>66.59590</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Group A moves from approximately 52.4 to 53.4 (a minimal shift), group B moves from approximately 48.3 to 56.6, and group C moves from approximately 51.1 to 66.6. The response grows across groups, as specified in the simulation.</p>
<div id="352147a0" class="cell" data-execution_count="3">
<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;"># Mixed ANOVA: condition is within-subjects (each subject has a control AND</span></span>
<span id="cb3-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a treatment value), group is between-subjects. Error(subject/condition)</span></span>
<span id="cb3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tells R that condition is nested within subject.</span></span>
<span id="cb3-4">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;">aov</span>(biomarker <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> condition <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;">Error</span>(subject <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> condition), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> df)</span>
<span id="cb3-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(model)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>
Error: subject
          Df Sum Sq Mean Sq F value  Pr(&gt;F)   
group      2  770.3   385.2   7.431 0.00173 **
Residuals 42 2177.0    51.8                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Error: subject:condition
                Df Sum Sq Mean Sq F value   Pr(&gt;F)    
condition        1 1527.8  1527.8  279.79  &lt; 2e-16 ***
group:condition  2  789.4   394.7   72.28 2.52e-14 ***
Residuals       42  229.4     5.5                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1</code></pre>
</div>
</div>
<p>The output contains two error strata, corresponding to the between-subjects and within-subjects portions of the design.</p>
<p>The <strong><code>subject</code> stratum</strong> tests the main effect of group (<img src="https://latex.codecogs.com/png.latex?p%20=%200.00173">): the three groups differ overall, averaging control and treatment together.</p>
<p>The <strong><code>subject:condition</code> stratum</strong> tests the main effect of condition (<img src="https://latex.codecogs.com/png.latex?p%20%3C%202%5Cmathrm%7Be%7D%7B-16%7D">) and, critically, the <strong>group × condition interaction</strong> (<img src="https://latex.codecogs.com/png.latex?p%20=%202.52%5Cmathrm%7Be%7D%7B-14%7D">).</p>
<blockquote class="blockquote">
<p><strong>Q: Which result answers the original question — did treatment work differently by group?</strong> A: The interaction term. Its significance indicates that the magnitude of the control-to-treatment change is not the same across groups A, B, and C. A significant main effect of condition alone would only indicate that biomarker levels changed on average; the interaction indicates that the treatment effect itself depends on group membership. Three separate paired t-tests, one per group, would indicate whether each group changed individually, but would provide no formal test of whether those three changes differed from one another — which is ordinarily the scientific question of interest in a treatment-comparison study.</p>
</blockquote>
<p>The table of F-statistics makes the interaction’s significance clear, but doesn’t show what that interaction actually looks like. The plot below does: each line traces one group’s mean biomarker level from control to treatment, with error bars showing the standard error of the mean. A mixed ANOVA with no interaction would produce three roughly parallel lines — all groups shifting by about the same amount. What the simulation shows instead is divergence: group C’s line rises steeply, group B’s rises more modestly, and group A’s is nearly flat.</p>
<div id="a322800e" class="cell" data-execution_count="4">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Group means and standard errors by condition, for the interaction plot</span></span>
<span id="cb5-2">summary_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;">aggregate</span>(biomarker <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> condition, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> df,</span>
<span id="cb5-3">                         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">FUN =</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;">c</span>(<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;">mean</span>(x), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd</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;">sqrt</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(x))))</span>
<span id="cb5-4">summary_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>(data.frame, summary_df)</span>
<span id="cb5-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(summary_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;">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;">"condition"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"se"</span>)</span>
<span id="cb5-6">summary_df</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 4</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">group</th>
<th data-quarto-table-cell-role="th" scope="col">condition</th>
<th data-quarto-table-cell-role="th" scope="col">mean</th>
<th data-quarto-table-cell-role="th" scope="col">se</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;fct&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;fct&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>A</td>
<td>control</td>
<td>52.42117</td>
<td>1.323583</td>
</tr>
<tr class="even">
<td>B</td>
<td>control</td>
<td>48.28969</td>
<td>1.286907</td>
</tr>
<tr class="odd">
<td>C</td>
<td>control</td>
<td>51.12821</td>
<td>1.045192</td>
</tr>
<tr class="even">
<td>A</td>
<td>treatment</td>
<td>53.37999</td>
<td>1.793629</td>
</tr>
<tr class="odd">
<td>B</td>
<td>treatment</td>
<td>56.58443</td>
<td>1.587070</td>
</tr>
<tr class="even">
<td>C</td>
<td>treatment</td>
<td>66.59590</td>
<td>1.105771</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="666f24eb" class="cell" data-execution_count="5">
<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">group_colors <span class="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;">A =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#4C72B0"</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;">"#DD8452"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">C =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#55A868"</span>)</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</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;">xlim =</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;">2.2</span>),</span>
<span id="cb6-4">     <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;">range</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(summary_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mean <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> summary_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>se, summary_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mean <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> summary_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>se)) <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;">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;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb6-5">     <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xaxt =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</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;">ylab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Biomarker level (mean \u00B1 SE)"</span>,</span>
<span id="cb6-6">     <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;">"Treatment effect by group: a group x condition interaction"</span>)</span>
<span id="cb6-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">axis</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;">at =</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="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;">"Control"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Treatment"</span>))</span>
<span id="cb6-8"></span>
<span id="cb6-9"><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>(summary_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group)) {</span>
<span id="cb6-10">  sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> summary_df[summary_df<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> g, ]</span>
<span id="cb6-11">  sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sub[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">order</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>condition), ]</span>
<span id="cb6-12">  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;">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>
<span id="cb6-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lines</span>(x, sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mean, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> group_colors[g], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lwd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</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;">"b"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cex =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.3</span>)</span>
<span id="cb6-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrows</span>(x, sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mean <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>se, x, sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mean <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>se, <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;">90</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">code =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="cb6-15">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</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;">col =</span> group_colors[g])</span>
<span id="cb6-16">}</span>
<span id="cb6-17"></span>
<span id="cb6-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">legend</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"topleft"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(summary_df<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;">col =</span> group_colors, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lwd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>,</span>
<span id="cb6-19">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Group"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bty =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/ttest_ANOVA/t-test-vs-anova-before-after-treatment_files/figure-html/cell-6-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Non-parallel lines are the visual signature of an interaction — and the degree of non-parallelism here (group C pulling sharply away from A and B) is exactly what produced the very small p-value on the <code>group:condition</code> term above. This plot and the ANOVA table are two views of the same result: one gives the formal test, the other shows what the tested pattern actually looks like in the data, which is often the more persuasive figure for a paper or presentation.</p>
</section>
<section id="assumptions-and-alternatives" class="level2" data-number="7">
<h2 data-number="7" class="anchored" data-anchor-id="assumptions-and-alternatives"><span class="header-section-number">7</span> Assumptions and Alternatives</h2>
<p>The mixed-design ANOVA carries the standard ANOVA assumptions of normally distributed residuals and homogeneity of variance across groups, together with sphericity for the within-subjects factor when more than two time points are present. Sphericity is automatically satisfied with only two levels, as in a single before/after comparison.</p>
<p>Where these assumptions are doubtful, two alternatives are available. A linear mixed-effects model, fit with <code>lme4</code> or <code>nlme</code>, accommodates unbalanced data and missing observations more gracefully than classical ANOVA while producing an equivalent interaction test. For small samples or markedly non-normal outcomes, a nonparametric alternative such as the Friedman test, combined with rank-based group comparisons, can be used, though these approaches test somewhat different hypotheses and offer less flexibility for interaction effects.</p>
</section>
<section id="conclusion" class="level2" data-number="8">
<h2 data-number="8" class="anchored" data-anchor-id="conclusion"><span class="header-section-number">8</span> Conclusion</h2>
<p>“t-test or ANOVA” is not, by itself, a well-posed question. The determining factor is the number of independent sources of variation present in the design. A before/after comparison within a single group constitutes one factor; a comparison across multiple groups introduces a second. When both are present together, as in a multi-group treatment study, the appropriate test is one built to model two factors and their interaction jointly — the mixed-design ANOVA. Substituting a t-test in this setting does not merely reduce statistical power; it silently discards the interaction test that the design was intended to answer.</p>


</section>

 ]]></description>
  <guid>https://bntechie.github.io/tutorials/ttest_ANOVA/t-test-vs-anova-before-after-treatment.html</guid>
  <pubDate>Tue, 04 Aug 2026 08:05:30 GMT</pubDate>
</item>
<item>
  <title>Generative AI and Prompt Engineering</title>
  <dc:creator>Nivedita </dc:creator>
  <link>https://bntechie.github.io/tutorials/promt_engineering/genai-prompt-engineering-tutorial.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<div class="thesis-hero-art">
<svg viewbox="0 0 700 260" xmlns="http://www.w3.org/2000/svg" font-family="IBM Plex Mono, monospace">
<rect x="0" y="0" width="700" height="260" fill="#fbfaf7"></rect><rect x="20" y="95" width="130" height="70" rx="6" fill="#f5f3ee" stroke="#d8d3c7" stroke-width="1.2"></rect><text x="85" y="122" text-anchor="middle" font-size="10.5" fill="#5b6b78">“Summarize</text><text x="85" y="136" text-anchor="middle" font-size="10.5" fill="#5b6b78">this result</text><text x="85" y="150" text-anchor="middle" font-size="10.5" fill="#5b6b78">in plain</text><text x="85" y="164" text-anchor="middle" font-size="10.5" fill="#5b6b78">language”</text><text x="85" y="85" text-anchor="middle" font-size="10" fill="#b9812c" letter-spacing="0.5">BARE PROMPT</text><g stroke="#2f6f6b" stroke-width="1.4" fill="none"><path d="M170 108 C 230 100, 260 110, 300 128" marker-end="url(#arrowFun)"></path><path d="M170 130 C 230 128, 260 128, 300 130" marker-end="url(#arrowFun)"></path><path d="M170 152 C 230 148, 260 138, 300 133" marker-end="url(#arrowFun)"></path><path d="M170 174 C 230 168, 260 145, 300 135" marker-end="url(#arrowFun)"></path></g><text x="172" y="103" font-size="9.5" fill="#1c2b39">+ persona</text><text x="172" y="188" font-size="9.5" fill="#1c2b39">+ context</text><text x="330" y="98" font-size="9.5" fill="#1c2b39">+ example</text><text x="330" y="200" font-size="9.5" fill="#1c2b39">+ format</text><rect x="300" y="105" width="90" height="55" rx="6" fill="#2f6f6b" opacity="0.12" stroke="#2f6f6b" stroke-width="1.4"></rect><text x="345" y="128" text-anchor="middle" font-size="10.5" fill="#1f4d4a" font-weight="600">LLM</text><text x="345" y="143" text-anchor="middle" font-size="8.5" fill="#5b6b78">token by</text><text x="345" y="154" text-anchor="middle" font-size="8.5" fill="#5b6b78">token</text><path d="M392 132 L 430 132" stroke="#1c2b39" stroke-width="1.4" marker-end="url(#arrowFun)"></path><g><line x1="450" y1="180" x2="450" y2="90" stroke="#d8d3c7" stroke-width="1"></line><line x1="450" y1="180" x2="600" y2="180" stroke="#d8d3c7" stroke-width="1"></line><rect x="462" y="165" width="14" height="15" fill="#5b6b78" opacity="0.35"></rect><rect x="484" y="150" width="14" height="30" fill="#5b6b78" opacity="0.45"></rect><rect x="506" y="100" width="14" height="80" fill="#b9812c"></rect><rect x="528" y="158" width="14" height="22" fill="#5b6b78" opacity="0.4"></rect><rect x="550" y="170" width="14" height="10" fill="#5b6b78" opacity="0.3"></rect></g><text x="513" y="90" text-anchor="middle" font-size="9" fill="#b9812c" font-weight="600">p = 0.87</text><text x="525" y="200" text-anchor="middle" font-size="10" fill="#5b6b78">sharper output</text><text x="525" y="213" text-anchor="middle" font-size="10" fill="#5b6b78">distribution</text><defs><marker id="arrowFun" markerwidth="9" markerheight="9" refx="7" refy="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 z" fill="#2f6f6b"></path></marker></defs>
</svg>
</div>
<div class="thesis-hero-caption">
A weak instruction and an engineered one reach the same model, but persona, context, example, and output format push the engineered version toward a single high-probability answer instead of a diffuse guess.
</div>
</div>
<section id="introduction" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="introduction"><span class="header-section-number">1</span> Introduction</h2>
<p>Generative AI denotes a class of systems that produce new content — text, images, audio, video, or code — rather than only classifying or scoring existing data. A model learns the statistical structure of a training corpus and then samples new instances consistent with that structure, as opposed to mapping fixed inputs onto a fixed set of output labels.</p>
<p>This tutorial covers the material in three layers. First, the conceptual layer: what generative models are, how large language models (LLMs) are trained, and how this differs from conventional machine learning. Second, the mechanical layer: how a prompt actually becomes an output, via token-level sampling — treated computationally, in R, using a toy model, so the abstraction is not left as a black box. Third, the applied layer: prompt engineering as a design discipline, common prompting strategies, and a survey of the current tool landscape, closing with practical guidance and known limitations.</p>
<p>Model and product names change quickly in this field. Where a specific product is named below, the description reflects its status as of mid-2026; several products referenced in earlier training material on this topic (GPT-3, GPT-4, Google Bard, DALL-E, Amazon CodeWhisperer) have since been superseded or renamed, and this is noted explicitly where relevant.</p>
</section>
<section id="what-generative-ai-produces" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="what-generative-ai-produces"><span class="header-section-number">2</span> What Generative AI Produces</h2>
<p>Three domains illustrate the breadth of the category:</p>
<p><strong>Text.</strong> Current-generation LLMs — OpenAI’s GPT-5 family, Anthropic’s Claude models, Google’s Gemini, and Meta’s open-weight Llama models — generate essays, code, and dialogue conditioned on a prompt.</p>
<p><strong>Images.</strong> Diffusion and autoregressive image models (Midjourney, Stable Diffusion, OpenAI’s GPT Image line, Adobe Firefly) convert a text description into a corresponding image.</p>
<p><strong>Audio and video.</strong> Tools such as Suno (music), ElevenLabs (voice), and Runway (video) apply the same generate-from-description paradigm to other modalities.</p>
<p>The common thread is not the modality but the training objective: the model is optimized to produce plausible continuations or reconstructions of its training distribution, not to output a predetermined answer.</p>
</section>
<section id="generative-ai-versus-conventional-machine-learning" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="generative-ai-versus-conventional-machine-learning"><span class="header-section-number">3</span> Generative AI versus Conventional Machine Learning</h2>
<p>The distinction is best drawn along five axes rather than treated as a single sharp boundary — a fraud-detection classifier and an LLM are both “machine learning” in the broad sense, but they differ systematically in what they are built to do.</p>
<div id="99b4f197" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.098040Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.070831Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:43.399068Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:43.389901Z&quot;}}" data-execution_count="1">
<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">ml_vs_genai <span class="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="cb1-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">aspect       =</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;">"Objective"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Typical output"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Typical training data"</span>,</span>
<span id="cb1-3">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dominant learning paradigm"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Common architectures"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Example task"</span>),</span>
<span id="cb1-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">machine_learning =</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;">"Predict a label or value from input features"</span>,</span>
<span id="cb1-5">                        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Class label, score, or continuous value"</span>,</span>
<span id="cb1-6">                        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Structured / tabular"</span>,</span>
<span id="cb1-7">                        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Supervised (labeled data)"</span>,</span>
<span id="cb1-8">                        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Linear/logistic regression, tree ensembles, SVM"</span>,</span>
<span id="cb1-9">                        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Flagging a fraudulent transaction"</span>),</span>
<span id="cb1-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">generative_ai =</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;">"Produce a new instance consistent with a learned distribution"</span>,</span>
<span id="cb1-11">                     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Text, image, audio, or video"</span>,</span>
<span id="cb1-12">                     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Large unstructured corpora (text, image, audio)"</span>,</span>
<span id="cb1-13">                     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Self-supervised pretraining, often followed by fine-tuning"</span>,</span>
<span id="cb1-14">                     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Transformer-based architectures (decoder-only LLMs, diffusion models)"</span>,</span>
<span id="cb1-15">                     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Drafting a paragraph explaining a result"</span>),</span>
<span id="cb1-16">  <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="cb1-17">)</span>
<span id="cb1-18"></span>
<span id="cb1-19"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(ml_vs_genai, <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;">FALSE</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>                     aspect                                machine_learning
                  Objective    Predict a label or value from input features
             Typical output         Class label, score, or continuous value
      Typical training data                            Structured / tabular
 Dominant learning paradigm                       Supervised (labeled data)
       Common architectures Linear/logistic regression, tree ensembles, SVM
               Example task               Flagging a fraudulent transaction
                                                         generative_ai
         Produce a new instance consistent with a learned distribution
                                          Text, image, audio, or video
                       Large unstructured corpora (text, image, audio)
            Self-supervised pretraining, often followed by fine-tuning
 Transformer-based architectures (decoder-only LLMs, diffusion models)
                              Drafting a paragraph explaining a result</code></pre>
</div>
</div>
</section>
<section id="large-language-models" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="large-language-models"><span class="header-section-number">4</span> Large Language Models</h2>
<p>An LLM is trained to predict the next token in a sequence given the tokens that precede it. Applied at scale over a large text corpus, this single objective — next-token prediction — is sufficient to produce a model that captures grammar, factual associations, and long-range discourse structure, without ever being given an explicit label for any of those properties. This is what makes the training self-supervised: the “label” at each position is simply the next token in the existing text, so no separate annotation step is required.</p>
<p><strong>Pretraining</strong> establishes the model’s general language competence over a broad corpus. <strong>Fine-tuning</strong> (and closely related techniques such as instruction tuning and reinforcement learning from human feedback) subsequently adapts a pretrained model toward following instructions reliably or performing well in a narrower domain — for instance, adapting a general-purpose model toward clinical or legal terminology.</p>
<blockquote class="blockquote">
<p><strong>Why does the distinction between pretraining and fine-tuning matter practically?</strong> A pretrained-only model tends to continue text rather than answer a question — asked “What is the capital of Finland?”, it may generate a plausible-looking follow-up question rather than a direct answer. Instruction tuning is what makes a model behave like an assistant that responds directly to a request, which is the behavior most users interact with in products such as ChatGPT or Claude.</p>
</blockquote>
<section id="why-llms-matter-in-practice" class="level3" data-number="4.1">
<h3 data-number="4.1" class="anchored" data-anchor-id="why-llms-matter-in-practice"><span class="header-section-number">4.1</span> Why LLMs matter in practice</h3>
<ul>
<li><strong>Communication and translation</strong> — real-time translation and multilingual content generation, without a separately trained model per language pair.</li>
<li><strong>Scalable content production</strong> — drafting at a volume and speed not practical for manual writing alone, subject to the fact-checking caveat discussed later.</li>
<li><strong>Personalization</strong> — tailoring phrasing, reading level, or emphasis to a stated audience.</li>
<li><strong>Routine-task automation</strong> — drafting emails, summarizing long documents, generating boilerplate code.</li>
<li><strong>Accessibility</strong> — text-to-speech and speech-to-text pipelines that lower barriers for users with visual or motor impairments.</li>
</ul>
</section>
</section>
<section id="prompt-engineering-as-a-design-problem" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="prompt-engineering-as-a-design-problem"><span class="header-section-number">5</span> Prompt Engineering as a Design Problem</h2>
<p>A prompt can be decomposed into a small number of largely independent components: a persona (the role the model should adopt), the instruction itself, contextual background, optional worked examples, and an output-format specification. Building these programmatically, rather than writing each prompt by hand, makes explicit what changes between an under-specified request and a well-constructed one — and is closer to a controlled comparison, in the experimental-design sense, than to freeform writing.</p>
<div id="6a177df6" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.611274Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.416047Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:43.762680Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:43.760489Z&quot;}}" data-execution_count="2">
<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">build_prompt <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>(instruction, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">persona =</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;">context =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>,</span>
<span id="cb3-2">                          <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">examples =</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;">output_format =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) {</span>
<span id="cb3-3">  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;">character</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb3-4">  <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>(persona))       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;">c</span>(parts, <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;">"Act as %s."</span>, persona))</span>
<span id="cb3-5">  <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>(context))       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;">c</span>(parts, <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;">"Context: %s"</span>, context))</span>
<span id="cb3-6">  <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>(examples))      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;">c</span>(parts, <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;">"Examples:</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;">%s"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(examples, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">collapse =</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)))</span>
<span id="cb3-7">  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;">c</span>(parts, <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;">"Task: %s"</span>, instruction))</span>
<span id="cb3-8">  <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>(output_format)) 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;">c</span>(parts, <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;">"Respond as: %s"</span>, output_format))</span>
<span id="cb3-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(parts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">collapse =</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;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-10">}</span>
<span id="cb3-11"></span>
<span id="cb3-12">weak_prompt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb3-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Explain what a Manhattan plot shows."</span></span>
<span id="cb3-14">)</span>
<span id="cb3-15"></span>
<span id="cb3-16">engineered_prompt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb3-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Explain what a Manhattan plot shows."</span>,</span>
<span id="cb3-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">persona =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a statistical genetics instructor addressing first-year PhD students"</span>,</span>
<span id="cb3-19">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">context =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The audience has taken introductory statistics but has not yet covered GWAS."</span>,</span>
<span id="cb3-20">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">output_format =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"three short paragraphs, ending with one sentence on how a significance threshold is chosen"</span></span>
<span id="cb3-21">)</span>
<span id="cb3-22"></span>
<span id="cb3-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(weak_prompt, <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\n</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;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, engineered_prompt, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Task: Explain what a Manhattan plot shows.

---

Act as a statistical genetics instructor addressing first-year PhD students.

Context: The audience has taken introductory statistics but has not yet covered GWAS.

Task: Explain what a Manhattan plot shows.

Respond as: three short paragraphs, ending with one sentence on how a significance threshold is chosen</code></pre>
</div>
</div>
</section>
<section id="from-prompt-to-output-simulating-token-sampling" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="from-prompt-to-output-simulating-token-sampling"><span class="header-section-number">6</span> From Prompt to Output: Simulating Token Sampling</h2>
<p>Given a fixed prompt, an LLM does not return a single deterministic string. At each position it assigns a score (logit) to every candidate next token, converts these scores into a probability distribution via the softmax function, and samples from that distribution. The <strong>temperature</strong> parameter rescales the logits before this conversion: low temperature sharpens the distribution toward the highest-scoring token (output closer to deterministic), while high temperature flattens it (more variable output). This is exactly why the same prompt, sent twice, can produce two different — but each individually plausible — responses.</p>
<p>This mechanism can be simulated directly with a toy vocabulary, without calling any external model.</p>
<div id="6a16b52e" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.768351Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.766207Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:43.819786Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:43.817425Z&quot;}}" data-execution_count="3">
<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">softmax <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>(logits, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">temperature =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) {</span>
<span id="cb5-2">  scaled <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> logits <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> temperature</span>
<span id="cb5-3">  exp_scaled <span class="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>(scaled <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>(scaled))  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># numerically stable</span></span>
<span id="cb5-4">  exp_scaled <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>(exp_scaled)</span>
<span id="cb5-5">}</span>
<span id="cb5-6"></span>
<span id="cb5-7">vocab  <span class="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;">"significant"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"suggestive"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"negligible"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"confounded"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"spurious"</span>)</span>
<span id="cb5-8">logits <span class="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;">4.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.1</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;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>)</span>
<span id="cb5-9"></span>
<span id="cb5-10">temperatures <span class="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.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</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.5</span>)</span>
<span id="cb5-11">prob_table <span class="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>(temperatures, <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;">softmax</span>(logits, t))</span>
<span id="cb5-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(prob_table) <span class="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;">"T="</span>, temperatures)</span>
<span id="cb5-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(prob_table) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> vocab</span>
<span id="cb5-14"></span>
<span id="cb5-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(prob_table, <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-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 5 × 4 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">T=0.2</th>
<th data-quarto-table-cell-role="th" scope="col">T=0.7</th>
<th data-quarto-table-cell-role="th" scope="col">T=1</th>
<th data-quarto-table-cell-role="th" scope="col">T=1.5</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">significant</th>
<td>0.996</td>
<td>0.817</td>
<td>0.710</td>
<td>0.575</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">suggestive</th>
<td>0.004</td>
<td>0.170</td>
<td>0.236</td>
<td>0.276</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">negligible</th>
<td>0.000</td>
<td>0.006</td>
<td>0.024</td>
<td>0.060</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">confounded</th>
<td>0.000</td>
<td>0.004</td>
<td>0.018</td>
<td>0.049</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">spurious</th>
<td>0.000</td>
<td>0.003</td>
<td>0.013</td>
<td>0.040</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The entropy of each distribution quantifies this concentration effect directly: low temperature yields low entropy (the model is close to deterministic), and high temperature moves the distribution toward uniform over the vocabulary.</p>
<div id="c3bc5bb5" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.825957Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.823615Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:43.853330Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:43.851672Z&quot;}}" data-execution_count="4">
<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">entropy <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="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>(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;">log</span>(p))</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb6-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">temperature =</span> temperatures,</span>
<span id="cb6-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">entropy     =</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;">apply</span>(prob_table, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, entropy), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb6-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">top_token   =</span> vocab[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(prob_table, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, which.max)]</span>
<span id="cb6-7">)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 4 × 3</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">temperature</th>
<th data-quarto-table-cell-role="th" scope="col">entropy</th>
<th data-quarto-table-cell-role="th" scope="col">top_token</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">T=0.2</th>
<td>0.2</td>
<td>0.026</td>
<td>significant</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">T=0.7</th>
<td>0.7</td>
<td>0.537</td>
<td>significant</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">T=1</th>
<td>1.0</td>
<td>0.800</td>
<td>significant</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">T=1.5</th>
<td>1.5</td>
<td>1.118</td>
<td>significant</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="zero-shot-few-shot-and-chain-of-thought-prompting" class="level2" data-number="7">
<h2 data-number="7" class="anchored" data-anchor-id="zero-shot-few-shot-and-chain-of-thought-prompting"><span class="header-section-number">7</span> Zero-Shot, Few-Shot, and Chain-of-Thought Prompting</h2>
<p>The three standard prompting strategies differ in how much structure is supplied before the task itself.</p>
<blockquote class="blockquote">
<p><strong>Zero-shot prompting</strong> — the model performs the task with no worked examples, relying entirely on knowledge acquired during training. Well suited to translation, general Q&amp;A, and straightforward classification.</p>
</blockquote>
<blockquote class="blockquote">
<p><strong>Few-shot prompting</strong> — the prompt includes several input–output examples before the actual task, which anchors the model to a specific desired format or style. Useful when the output must follow a particular structure — consistent-style content generation, pattern-based classification, structured summarization.</p>
</blockquote>
<blockquote class="blockquote">
<p><strong>Chain-of-thought (CoT) prompting</strong> — the model is guided through explicit intermediate reasoning steps before producing a final answer. This is the most reliable strategy for multi-step arithmetic, logic, and other tasks where an unstructured single-shot answer is prone to skipping a step.</p>
</blockquote>
<p>These can be built as three thin wrappers around the same <code>build_prompt()</code> function defined above, which makes the structural difference between the strategies explicit rather than a matter of writing style.</p>
<div id="316a4cc4" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.859526Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.857747Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:43.889330Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:43.886254Z&quot;}}" data-execution_count="5">
<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">zero_shot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb7-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Classify the following variant consequence as high, moderate, or low impact: stop_gained"</span></span>
<span id="cb7-3">)</span>
<span id="cb7-4"></span>
<span id="cb7-5">few_shot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb7-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Classify the following variant consequence as high, moderate, or low impact: stop_gained"</span>,</span>
<span id="cb7-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">examples =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb7-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"missense_variant -&gt; moderate impact"</span>,</span>
<span id="cb7-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"synonymous_variant -&gt; low impact"</span>,</span>
<span id="cb7-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"frameshift_variant -&gt; high impact"</span></span>
<span id="cb7-11">  )</span>
<span id="cb7-12">)</span>
<span id="cb7-13"></span>
<span id="cb7-14">chain_of_thought <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb7-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Classify the following variant consequence as high, moderate, or low impact: stop_gained"</span>,</span>
<span id="cb7-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">context =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(</span>
<span id="cb7-17">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Reason step by step: (1) identify what the consequence term means at the"</span>,</span>
<span id="cb7-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"protein level, (2) assess whether it truncates or disrupts the reading frame,"</span>,</span>
<span id="cb7-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(3) map that assessment to an impact category, (4) state the final classification."</span></span>
<span id="cb7-20">  )</span>
<span id="cb7-21">)</span>
<span id="cb7-22"></span>
<span id="cb7-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ZERO-SHOT</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>, zero_shot, <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\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>,</span>
<span id="cb7-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FEW-SHOT</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>, few_shot, <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\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>,</span>
<span id="cb7-25">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CHAIN-OF-THOUGHT</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>, chain_of_thought, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>ZERO-SHOT
Task: Classify the following variant consequence as high, moderate, or low impact: stop_gained

FEW-SHOT
Examples:
missense_variant -&gt; moderate impact
synonymous_variant -&gt; low impact
frameshift_variant -&gt; high impact

Task: Classify the following variant consequence as high, moderate, or low impact: stop_gained

CHAIN-OF-THOUGHT
Context: Reason step by step: (1) identify what the consequence term means at the protein level, (2) assess whether it truncates or disrupts the reading frame, (3) map that assessment to an impact category, (4) state the final classification.

Task: Classify the following variant consequence as high, moderate, or low impact: stop_gained</code></pre>
</div>
</div>
</section>
<section id="a-heuristic-for-prompt-specificity" class="level2" data-number="8">
<h2 data-number="8" class="anchored" data-anchor-id="a-heuristic-for-prompt-specificity"><span class="header-section-number">8</span> A Heuristic for Prompt Specificity</h2>
<p>The qualitative distinction between a “weak” and a “well-engineered” prompt can be given a rough quantitative proxy: count the structural elements present — an explicit role, contextual background, at least one worked example, and an explicit output format. This is not a validated metric, but it makes concrete what “well-engineered” is standing in for, and gives a way to compare prompts before sending either to a model.</p>
<div id="edbf55f1" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.896914Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.892978Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:43.947244Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:43.945244Z&quot;}}" data-execution_count="6">
<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">specificity_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>(prompt) {</span>
<span id="cb9-2">  has_role    <span class="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;">"^Act as"</span>, prompt)</span>
<span id="cb9-3">  has_context <span class="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;">"Context:|Reason step by step"</span>, prompt)</span>
<span id="cb9-4">  has_example <span class="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;">"Examples:|-&gt;"</span>, prompt)</span>
<span id="cb9-5">  has_format  <span class="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;">"Respond as:"</span>, prompt)</span>
<span id="cb9-6">  word_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;">lengths</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">strsplit</span>(prompt, <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;">s+"</span>))</span>
<span id="cb9-7"></span>
<span id="cb9-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb9-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">role =</span> has_role, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">context =</span> has_context,</span>
<span id="cb9-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">example =</span> has_example, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">output_format =</span> has_format,</span>
<span id="cb9-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">word_count =</span> word_count,</span>
<span id="cb9-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">structure_score =</span> has_role <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> has_context <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> has_example <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> has_format</span>
<span id="cb9-13">  )</span>
<span id="cb9-14">}</span>
<span id="cb9-15"></span>
<span id="cb9-16">prompts <span class="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="at" style="color: #657422;
background-color: null;
font-style: inherit;">weak =</span> weak_prompt, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">engineered =</span> engineered_prompt,</span>
<span id="cb9-17">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">zero_shot =</span> zero_shot, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">few_shot =</span> few_shot, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cot =</span> chain_of_thought)</span>
<span id="cb9-18"></span>
<span id="cb9-19"><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>(prompts, specificity_score))</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 5 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">role</th>
<th data-quarto-table-cell-role="th" scope="col">context</th>
<th data-quarto-table-cell-role="th" scope="col">example</th>
<th data-quarto-table-cell-role="th" scope="col">output_format</th>
<th data-quarto-table-cell-role="th" scope="col">word_count</th>
<th data-quarto-table-cell-role="th" scope="col">structure_score</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">weak</th>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>7</td>
<td>0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">engineered</th>
<td>TRUE</td>
<td>TRUE</td>
<td>FALSE</td>
<td>TRUE</td>
<td>46</td>
<td>3</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">zero_shot</th>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>13</td>
<td>0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">few_shot</th>
<td>FALSE</td>
<td>FALSE</td>
<td>TRUE</td>
<td>FALSE</td>
<td>26</td>
<td>1</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">cot</th>
<td>FALSE</td>
<td>TRUE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>52</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The <code>structure_score</code> column separates the five prompts cleanly: the weak prompt scores zero, the engineered version scores three, and the three named strategies each add exactly one structural element beyond a bare instruction — context for chain-of-thought, worked examples for few-shot, nothing beyond the instruction itself for zero-shot.</p>
</section>
<section id="applying-llms-to-academic-and-professional-tasks" class="level2" data-number="9">
<h2 data-number="9" class="anchored" data-anchor-id="applying-llms-to-academic-and-professional-tasks"><span class="header-section-number">9</span> Applying LLMs to Academic and Professional Tasks</h2>
<p>Current general-purpose LLMs support four broad capabilities relevant to this kind of work: natural language understanding (following multi-part instructions), text generation (drafting essays, reports, and code), information retrieval across general topics (subject to the currency limitations discussed later), and step-by-step problem solving.</p>
<p>Applied by subject, three patterns recur:</p>
<ul>
<li><strong>Quantitative subjects</strong> (mathematics, statistics) — worked, stepwise solutions and clarification of terminology; chain-of-thought prompting is particularly effective here.</li>
<li><strong>Conceptual subjects</strong> (natural sciences) — explanation at a specified level of background knowledge, and generation of illustrative examples or experiment ideas.</li>
<li><strong>Interpretive subjects</strong> (literature, argumentation) — thematic analysis and drafting assistance, where the underlying claims still require the user’s own verification and judgment.</li>
</ul>
<p>At the workflow level rather than the subject level, three uses account for most practical value: simplifying research (summarizing long material into key points), generating ideas (structured brainstorming and outlining), and producing explanations calibrated to a stated audience (via analogy or simplification).</p>
<section id="a-worked-example-reusing-build_prompt-for-a-recurring-task" class="level3" data-number="9.1">
<h3 data-number="9.1" class="anchored" data-anchor-id="a-worked-example-reusing-build_prompt-for-a-recurring-task"><span class="header-section-number">9.1</span> A worked example: reusing <code>build_prompt()</code> for a recurring task</h3>
<p>A common pattern in practice is to fix most of a prompt’s structure in advance and defer one piece of task-specific data to a follow-up turn. This reuses the same <code>build_prompt()</code> constructor already defined, applied to a resume-drafting task with an explicit “wait for further input” instruction.</p>
<div id="d32ef887" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.953223Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.951864Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:43.969879Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:43.967812Z&quot;}}" data-execution_count="7">
<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">resume_prompt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb10-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(</span>
<span id="cb10-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Draft a resume for a Data Science role with 4 years of experience across"</span>,</span>
<span id="cb10-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"two prior positions. Use standard sections: Contact Information,"</span>,</span>
<span id="cb10-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Professional Summary, Work Experience, Education, Skills, Certifications."</span>,</span>
<span id="cb10-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wait for a job description to be supplied before finalizing content."</span></span>
<span id="cb10-7">  ),</span>
<span id="cb10-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">persona =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a resume writer specializing in data science roles"</span>,</span>
<span id="cb10-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">context =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The candidate has 4 years of experience across 2 companies."</span>,</span>
<span id="cb10-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">output_format =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a standard resume layout with the sections listed above"</span></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;">cat</span>(resume_prompt)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Act as a resume writer specializing in data science roles.

Context: The candidate has 4 years of experience across 2 companies.

Task: Draft a resume for a Data Science role with 4 years of experience across two prior positions. Use standard sections: Contact Information, Professional Summary, Work Experience, Education, Skills, Certifications. Wait for a job description to be supplied before finalizing content.

Respond as: a standard resume layout with the sections listed above</code></pre>
</div>
</div>
<p>This pattern — templating the reusable structure while leaving the variable input (here, the job description) to be supplied afterward — generalizes to any workflow where the same task recurs with different data each time, for example generating a plain-language summary of a <code>coloc.abf</code> result for different gene–trait pairs.</p>
</section>
</section>
<section id="the-generative-ai-tool-landscape" class="level2" data-number="10">
<h2 data-number="10" class="anchored" data-anchor-id="the-generative-ai-tool-landscape"><span class="header-section-number">10</span> The Generative AI Tool Landscape</h2>
<p>The tool landscape in this field moves quickly, so this section is organized by category, with model or product names given as illustrative examples current as of mid-2026 rather than a fixed catalog. A few notable changes relative to material from a year or two prior: <strong>Google’s Bard was renamed Gemini in February 2024</strong>; <strong>Amazon’s CodeWhisperer was rebranded as Amazon Q Developer in April 2024</strong>; <strong>OpenAI retired the DALL-E brand in 2026</strong>, consolidating image generation under the GPT Image line; and video models such as Runway have moved through several major generations (Gen-2 → Gen-4.5) since earlier overviews of this space were written.</p>
<div id="e88e8113" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.975630Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.973452Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:43.993340Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:43.991697Z&quot;}}" data-execution_count="8">
<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">tool_landscape <span class="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-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">category =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb12-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Text generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Text generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Text generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Text generation"</span>,</span>
<span id="cb12-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Image generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Image generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Image generation"</span>,</span>
<span id="cb12-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Code generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Code generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Code generation"</span>,</span>
<span id="cb12-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Audio &amp; music"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Audio &amp; music"</span>,</span>
<span id="cb12-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Video generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Video generation"</span>,</span>
<span id="cb12-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Multimodal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Multimodal"</span>,</span>
<span id="cb12-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Open-weight / local"</span></span>
<span id="cb12-10">  ),</span>
<span id="cb12-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">example_tool =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb12-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ChatGPT (OpenAI)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Claude (Anthropic)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gemini (Google)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Llama (Meta, open-weight)"</span>,</span>
<span id="cb12-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Midjourney"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Stable Diffusion (Stability AI)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GPT Image (OpenAI)"</span>,</span>
<span id="cb12-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GitHub Copilot"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Amazon Q Developer"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"StarCoder (Hugging Face / BigCode)"</span>,</span>
<span id="cb12-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Suno (music)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ElevenLabs (voice)"</span>,</span>
<span id="cb12-16">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Runway"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Synthesia"</span>,</span>
<span id="cb12-17">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Claude / GPT / Gemini (vision-enabled)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Multimodal open models (e.g. IDEFICS-style)"</span>,</span>
<span id="cb12-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ollama / LM Studio for local inference"</span></span>
<span id="cb12-19">  ),</span>
<span id="cb12-20">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">primary_use =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb12-21">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"General-purpose conversational assistant"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"General-purpose assistant, long-document handling"</span>,</span>
<span id="cb12-22">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Conversational assistant integrated with Google services"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Open-weight models for self-hosted or fine-tuned use"</span>,</span>
<span id="cb12-23">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Stylized, artistic image generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Open-source, locally runnable image generation"</span>,</span>
<span id="cb12-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Native image generation integrated into a chat assistant"</span>,</span>
<span id="cb12-25">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"In-editor code completion and generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AWS-integrated coding and cloud-resource assistant"</span>,</span>
<span id="cb12-26">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Open-source code-focused language model"</span>,</span>
<span id="cb12-27">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Text-to-song generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Realistic voice synthesis and cloning"</span>,</span>
<span id="cb12-28">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Text- and image-conditioned video generation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Script-to-video with avatar presenters"</span>,</span>
<span id="cb12-29">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Combined text, image, and document reasoning"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Open research models combining vision and language"</span>,</span>
<span id="cb12-30">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Running open-weight LLMs on local hardware"</span></span>
<span id="cb12-31">  ),</span>
<span id="cb12-32">  <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="cb12-33">)</span>
<span id="cb12-34"></span>
<span id="cb12-35"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(tool_landscape, <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;">FALSE</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>            category                                example_tool
     Text generation                            ChatGPT (OpenAI)
     Text generation                          Claude (Anthropic)
     Text generation                             Gemini (Google)
     Text generation                   Llama (Meta, open-weight)
    Image generation                                  Midjourney
    Image generation             Stable Diffusion (Stability AI)
    Image generation                          GPT Image (OpenAI)
     Code generation                              GitHub Copilot
     Code generation                          Amazon Q Developer
     Code generation          StarCoder (Hugging Face / BigCode)
       Audio &amp; music                                Suno (music)
       Audio &amp; music                          ElevenLabs (voice)
    Video generation                                      Runway
    Video generation                                   Synthesia
          Multimodal      Claude / GPT / Gemini (vision-enabled)
          Multimodal Multimodal open models (e.g. IDEFICS-style)
 Open-weight / local      Ollama / LM Studio for local inference
                                              primary_use
                 General-purpose conversational assistant
        General-purpose assistant, long-document handling
 Conversational assistant integrated with Google services
     Open-weight models for self-hosted or fine-tuned use
                      Stylized, artistic image generation
           Open-source, locally runnable image generation
 Native image generation integrated into a chat assistant
                 In-editor code completion and generation
       AWS-integrated coding and cloud-resource assistant
                  Open-source code-focused language model
                                  Text-to-song generation
                    Realistic voice synthesis and cloning
             Text- and image-conditioned video generation
                   Script-to-video with avatar presenters
             Combined text, image, and document reasoning
       Open research models combining vision and language
               Running open-weight LLMs on local hardware</code></pre>
</div>
</div>
<blockquote class="blockquote">
<p><strong>A caution about tool inventories in a fast-moving field.</strong> Any fixed list like the one above is a snapshot, not a durable reference — model names, ownership, and even entire product lines (DALL-E being the clearest recent example) change on a timescale of months. Treat categories as more stable than the specific example filling each row, and verify current status before citing a specific tool in published material.</p>
</blockquote>
</section>
<section id="best-practices" class="level2" data-number="11">
<h2 data-number="11" class="anchored" data-anchor-id="best-practices"><span class="header-section-number">11</span> Best Practices</h2>
<p>The techniques covered above condense into a short set of practical habits:</p>
<ol type="1">
<li>State the task precisely rather than open-endedly — specificity is the single largest lever on output quality.</li>
<li>Assign a persona when the task benefits from a particular voice or expertise framing.</li>
<li>Supply context the model cannot otherwise infer (audience, constraints, prior decisions).</li>
<li>Treat the first response as a draft — iterative refinement is standard practice, not a sign of a failed first attempt.</li>
<li>Verify factual claims in the output against a primary source before relying on them.</li>
<li>Match the tool to the modality of the task — a text model is not the right tool for an image-generation request, and vice versa.</li>
<li>Avoid placing sensitive personal or proprietary information into a prompt sent to a third-party service.</li>
<li>Save prompt templates that work well for recurring tasks, following the reusable-constructor pattern demonstrated above.</li>
</ol>
</section>
<section id="limitations-of-current-generative-ai-systems" class="level2" data-number="12">
<h2 data-number="12" class="anchored" data-anchor-id="limitations-of-current-generative-ai-systems"><span class="header-section-number">12</span> Limitations of Current Generative AI Systems</h2>
<ul>
<li><strong>Fluency is not the same as correctness.</strong> A model can produce confident, well-formatted, and factually wrong output; the sampling mechanism described above optimizes for plausibility given training data, not for truth.</li>
<li><strong>No grounded fact-checking by default.</strong> Absent a retrieval or search step, a response reflects patterns learned during training rather than a verified lookup.</li>
<li><strong>Bias inheritance.</strong> Systematic patterns present in training data can be reproduced in output, including underrepresentation or skewed framing of certain groups or viewpoints.</li>
<li><strong>Knowledge currency.</strong> A model’s default knowledge is bounded by its training cutoff; anything after that date requires an explicit retrieval or search capability, not the base model alone.</li>
<li><strong>Miscalibrated confidence.</strong> Language models are not reliably self-aware of their own uncertainty; a wrong answer is often phrased with the same confidence as a correct one.</li>
<li><strong>Data handling.</strong> Prompts submitted to a hosted service may be logged or used according to that provider’s data policy; sensitive data warrants caution.</li>
<li><strong>Not a substitute for domain judgment.</strong> These systems are best used as a drafting and exploration aid, with a domain expert retaining responsibility for the final claim or decision.</li>
</ul>
</section>
<section id="summary" class="level2" data-number="13">
<h2 data-number="13" class="anchored" data-anchor-id="summary"><span class="header-section-number">13</span> Summary</h2>
<p>Generative AI is distinguished from conventional machine learning by its objective (producing new content consistent with a learned distribution, rather than predicting a label) and by its typical training regime (self-supervised pretraining on large unstructured corpora, often followed by instruction fine-tuning). LLMs are the text-generation instance of this category, and the process by which a fixed prompt becomes a specific output is governed by token-level sampling — softmax over logits, tuned by temperature — which is directly simulable and was demonstrated above without reference to any specific vendor’s model.</p>
<p>Prompt engineering is best treated as a compositional design problem: persona, instruction, context, examples, and output format are largely independent factors that can be manipulated and combined programmatically, and zero-shot, few-shot, and chain-of-thought prompting are three points along a single axis of increasing structural scaffolding rather than unrelated techniques. This gives a concrete basis — the <code>build_prompt()</code> constructor and the <code>specificity_score()</code> heuristic developed in this notebook — for evaluating and improving a prompt before sending it to any model, current or future.</p>
</section>
<section id="references" class="level2" data-number="14">
<h2 data-number="14" class="anchored" data-anchor-id="references"><span class="header-section-number">14</span> References</h2>
<ul>
<li>Vaswani et al., “Attention Is All You Need” (2017) — <a href="https://arxiv.org/abs/1706.03762">arXiv:1706.03762</a></li>
<li>Brown et al., “Language Models are Few-Shot Learners” (2020) — <a href="https://arxiv.org/abs/2005.14165">arXiv:2005.14165</a></li>
<li>Ouyang et al., “Training Language Models to Follow Instructions” (2022) — <a href="https://arxiv.org/abs/2203.02155">arXiv:2203.02155</a></li>
<li>“A Survey of Prompt Engineering Techniques” (2023) — <a href="https://arxiv.org/abs/2302.11382">arXiv:2302.11382</a></li>
<li>“An Overview of Large Language Models” (2023) — <a href="https://arxiv.org/abs/2303.18223">arXiv:2303.18223</a></li>
<li>Wei et al., “Chain-of-Thought Prompting Elicits Reasoning in LLMs” (2022) — <a href="https://arxiv.org/abs/2201.11903">arXiv:2201.11903</a></li>
</ul>
</section>
<section id="try-it-yourself" class="level2" data-number="15">
<h2 data-number="15" class="anchored" data-anchor-id="try-it-yourself"><span class="header-section-number">15</span> Try It Yourself</h2>
<ol type="1">
<li>Extend <code>specificity_score()</code> to also flag prompts that specify a maximum output length, and re-score the five example prompts from earlier in this notebook.</li>
<li>Modify the toy vocabulary and logits in the sampling section to model a near-tied scenario between two tokens, and compare the resulting entropy curve across temperatures.</li>
<li>Write a <code>build_prompt()</code> call for a task from your own tutorial pipeline — for example, a plain-language summary of a <code>coloc.abf</code> result for a general audience — and score it before and after adding context and an output format.</li>
<li>Pick one row of the tool landscape table and verify its current status against the vendor’s own documentation; note anything that has changed since this notebook was written.</li>
</ol>
</section>
<section id="solutions" class="level2" data-number="16">
<h2 data-number="16" class="anchored" data-anchor-id="solutions"><span class="header-section-number">16</span> Solutions</h2>
<p>The four exercises above are worked below, reusing the functions and objects already defined earlier in this notebook.</p>
<section id="solution-1-extending-specificity_score-with-a-length-constraint" class="level3" data-number="16.1">
<h3 data-number="16.1" class="anchored" data-anchor-id="solution-1-extending-specificity_score-with-a-length-constraint"><span class="header-section-number">16.1</span> Solution 1: Extending <code>specificity_score()</code> with a length constraint</h3>
<p>The extension follows the same pattern as the existing structural checks: search the prompt text for a marker phrase, here treating any mention of a numeric limit alongside a length-related word (<code>word</code>, <code>sentence</code>, <code>paragraph</code>) as evidence that an output-length constraint was specified.</p>
<div id="ac132ec8" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:43.999619Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:43.997428Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:44.039312Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:44.036922Z&quot;}}" data-execution_count="9">
<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">specificity_score_v2 <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>(prompt) {</span>
<span id="cb14-2">  has_role    <span class="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;">"^Act as"</span>, prompt)</span>
<span id="cb14-3">  has_context <span class="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;">"Context:|Reason step by step"</span>, prompt)</span>
<span id="cb14-4">  has_example <span class="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;">"Examples:|-&gt;"</span>, prompt)</span>
<span id="cb14-5">  has_format  <span class="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;">"Respond as:"</span>, prompt)</span>
<span id="cb14-6">  has_length  <span class="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;">"</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;">d+</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;">s*(word|sentence|paragraph)"</span>, prompt, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ignore.case =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb14-7">  word_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;">lengths</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">strsplit</span>(prompt, <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;">s+"</span>))</span>
<span id="cb14-8"></span>
<span id="cb14-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb14-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">role =</span> has_role, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">context =</span> has_context,</span>
<span id="cb14-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">example =</span> has_example, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">output_format =</span> has_format,</span>
<span id="cb14-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length_constraint =</span> has_length,</span>
<span id="cb14-13">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">word_count =</span> word_count,</span>
<span id="cb14-14">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">structure_score =</span> has_role <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> has_context <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> has_example <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> has_format <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> has_length</span>
<span id="cb14-15">  )</span>
<span id="cb14-16">}</span>
<span id="cb14-17"></span>
<span id="cb14-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Re-score the five prompts already defined earlier in the notebook</span></span>
<span id="cb14-19"><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>(prompts, specificity_score_v2))</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 5 × 7</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">role</th>
<th data-quarto-table-cell-role="th" scope="col">context</th>
<th data-quarto-table-cell-role="th" scope="col">example</th>
<th data-quarto-table-cell-role="th" scope="col">output_format</th>
<th data-quarto-table-cell-role="th" scope="col">length_constraint</th>
<th data-quarto-table-cell-role="th" scope="col">word_count</th>
<th data-quarto-table-cell-role="th" scope="col">structure_score</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">weak</th>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>7</td>
<td>0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">engineered</th>
<td>TRUE</td>
<td>TRUE</td>
<td>FALSE</td>
<td>TRUE</td>
<td>FALSE</td>
<td>46</td>
<td>3</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">zero_shot</th>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>13</td>
<td>0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">few_shot</th>
<td>FALSE</td>
<td>FALSE</td>
<td>TRUE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>26</td>
<td>1</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">cot</th>
<td>FALSE</td>
<td>TRUE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>52</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>None of the five original example prompts specified a numeric output length, so <code>length_constraint</code> is <code>FALSE</code> throughout and the <code>structure_score</code> values are unchanged from the earlier table. Adding a length-constrained prompt confirms the new check actually fires:</p>
<div id="3246c6c0" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:44.044503Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:44.042572Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:44.069162Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:44.067498Z&quot;}}" data-execution_count="10">
<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">length_constrained_prompt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb15-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Explain what a Manhattan plot shows."</span>,</span>
<span id="cb15-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">output_format =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no more than 3 sentences"</span></span>
<span id="cb15-4">)</span>
<span id="cb15-5"></span>
<span id="cb15-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">specificity_score_v2</span>(length_constrained_prompt)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 7</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">role</th>
<th data-quarto-table-cell-role="th" scope="col">context</th>
<th data-quarto-table-cell-role="th" scope="col">example</th>
<th data-quarto-table-cell-role="th" scope="col">output_format</th>
<th data-quarto-table-cell-role="th" scope="col">length_constraint</th>
<th data-quarto-table-cell-role="th" scope="col">word_count</th>
<th data-quarto-table-cell-role="th" scope="col">structure_score</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>TRUE</td>
<td>TRUE</td>
<td>14</td>
<td>2</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="solution-2-a-near-tied-vocabulary-and-its-entropy-curve" class="level3" data-number="16.2">
<h3 data-number="16.2" class="anchored" data-anchor-id="solution-2-a-near-tied-vocabulary-and-its-entropy-curve"><span class="header-section-number">16.2</span> Solution 2: A near-tied vocabulary and its entropy curve</h3>
<p>The original vocabulary had one dominant token (<code>significant</code>, logit 4.2) well ahead of the rest. Here two tokens are given nearly identical logits, which should push entropy higher at every temperature relative to the original, since the distribution can no longer collapse onto a single clear winner even at low temperature.</p>
<div id="b7094d25" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:44.075007Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:44.073220Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:44.107910Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:44.105484Z&quot;}}" data-execution_count="11">
<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">vocab_tied  <span class="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;">"significant"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"suggestive"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"negligible"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"confounded"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"spurious"</span>)</span>
<span id="cb16-2">logits_tied <span class="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;">3.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.9</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;">0.5</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;"># top two logits nearly tied</span></span>
<span id="cb16-3"></span>
<span id="cb16-4">prob_table_tied <span class="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>(temperatures, <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;">softmax</span>(logits_tied, t))</span>
<span id="cb16-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(prob_table_tied) <span class="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;">"T="</span>, temperatures)</span>
<span id="cb16-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(prob_table_tied) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> vocab_tied</span>
<span id="cb16-7"></span>
<span id="cb16-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(prob_table_tied, <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-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 5 × 4 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">T=0.2</th>
<th data-quarto-table-cell-role="th" scope="col">T=0.7</th>
<th data-quarto-table-cell-role="th" scope="col">T=1</th>
<th data-quarto-table-cell-role="th" scope="col">T=1.5</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">significant</th>
<td>0.622</td>
<td>0.511</td>
<td>0.463</td>
<td>0.398</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">suggestive</th>
<td>0.378</td>
<td>0.443</td>
<td>0.419</td>
<td>0.373</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">negligible</th>
<td>0.000</td>
<td>0.022</td>
<td>0.051</td>
<td>0.092</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">confounded</th>
<td>0.000</td>
<td>0.014</td>
<td>0.038</td>
<td>0.075</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">spurious</th>
<td>0.000</td>
<td>0.009</td>
<td>0.028</td>
<td>0.062</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="b03f126d" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:44.113075Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:44.111364Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:44.138195Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:44.135816Z&quot;}}" data-execution_count="12">
<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">comparison <span class="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="cb17-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">temperature       =</span> temperatures,</span>
<span id="cb17-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">entropy_original  =</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;">apply</span>(prob_table, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, entropy), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb17-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">entropy_near_tied =</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;">apply</span>(prob_table_tied, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, entropy), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb17-5">)</span>
<span id="cb17-6">comparison<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>entropy_increase <span class="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>(comparison<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>entropy_near_tied <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> comparison<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>entropy_original, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb17-7">comparison</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 4 × 4</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">temperature</th>
<th data-quarto-table-cell-role="th" scope="col">entropy_original</th>
<th data-quarto-table-cell-role="th" scope="col">entropy_near_tied</th>
<th data-quarto-table-cell-role="th" scope="col">entropy_increase</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">T=0.2</th>
<td>0.2</td>
<td>0.026</td>
<td>0.663</td>
<td>0.637</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">T=0.7</th>
<td>0.7</td>
<td>0.537</td>
<td>0.893</td>
<td>0.356</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">T=1</th>
<td>1.0</td>
<td>0.800</td>
<td>1.098</td>
<td>0.298</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">T=1.5</th>
<td>1.5</td>
<td>1.118</td>
<td>1.320</td>
<td>0.202</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The near-tied vocabulary has strictly higher entropy than the original at every temperature, and the gap is largest at low temperature (<code>T=0.2</code>): with a single dominant token, low temperature nearly always resolves to that token, but with two tokens close in score, even a sharpening transformation cannot fully separate them. As temperature increases, both distributions approach the same uniform-entropy ceiling, so the two curves converge — the effect of a near-tie is strongest exactly where it is least intuitive, at low temperature, not high.</p>
</section>
<section id="solution-3-a-coloc.abf-summary-prompt-before-and-after-engineering" class="level3" data-number="16.3">
<h3 data-number="16.3" class="anchored" data-anchor-id="solution-3-a-coloc.abf-summary-prompt-before-and-after-engineering"><span class="header-section-number">16.3</span> Solution 3: A <code>coloc.abf</code> summary prompt, before and after engineering</h3>
<p>A minimal version of this task and an engineered version, scored with <code>specificity_score()</code> for direct comparison.</p>
<div id="d0ac8662" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-08-04T01:37:44.143789Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-08-04T01:37:44.141555Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-08-04T01:37:44.172234Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-08-04T01:37:44.169936Z&quot;}}" data-execution_count="13">
<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">coloc_weak <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb18-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Summarize this coloc.abf result in plain language."</span></span>
<span id="cb18-3">)</span>
<span id="cb18-4"></span>
<span id="cb18-5">coloc_engineered <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">build_prompt</span>(</span>
<span id="cb18-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">instruction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Summarize this coloc.abf result in plain language: PP4 = 0.87, PP3 = 0.09, PP0-PP2 negligible."</span>,</span>
<span id="cb18-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">persona =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a genetic epidemiologist writing for a non-specialist collaborator"</span>,</span>
<span id="cb18-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">context =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(</span>
<span id="cb18-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PP4 is the posterior probability that the GWAS and eQTL signals share a"</span>,</span>
<span id="cb18-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"single causal variant; PP3 is the probability of two distinct causal"</span>,</span>
<span id="cb18-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"variants at the same locus."</span></span>
<span id="cb18-12">  ),</span>
<span id="cb18-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">output_format =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"two sentences, avoiding statistical jargon where possible"</span></span>
<span id="cb18-14">)</span>
<span id="cb18-15"></span>
<span id="cb18-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb18-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">specificity_score</span>(coloc_weak),</span>
<span id="cb18-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">specificity_score</span>(coloc_engineered)</span>
<span id="cb18-19">)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 2 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">role</th>
<th data-quarto-table-cell-role="th" scope="col">context</th>
<th data-quarto-table-cell-role="th" scope="col">example</th>
<th data-quarto-table-cell-role="th" scope="col">output_format</th>
<th data-quarto-table-cell-role="th" scope="col">word_count</th>
<th data-quarto-table-cell-role="th" scope="col">structure_score</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>FALSE</td>
<td>8</td>
<td>0</td>
</tr>
<tr class="even">
<td>TRUE</td>
<td>TRUE</td>
<td>FALSE</td>
<td>TRUE</td>
<td>65</td>
<td>3</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>As with the earlier examples, adding persona, context, and an output-format constraint raises the structure score from 0 to 3; the qualitative difference this makes to an actual model response would be that the weak version leaves both the intended audience and the meaning of PP4/PP3 unstated, while the engineered version fixes both before the request reaches the model.</p>
</section>
<section id="solution-4-verifying-one-row-of-the-tool-landscape-table" class="level3" data-number="16.4">
<h3 data-number="16.4" class="anchored" data-anchor-id="solution-4-verifying-one-row-of-the-tool-landscape-table"><span class="header-section-number">16.4</span> Solution 4: Verifying one row of the tool landscape table</h3>
<p>Taking the <strong>Runway</strong> row (Video generation) as the example. The table entry describes Runway generically as a “text- and image-conditioned video generation” tool, without pinning a version number — which was a deliberate choice, since version-specific claims are exactly what goes stale fastest in this space. Checking against Runway’s own release material as of mid-2026:</p>
<ul>
<li>Runway’s current flagship is <strong>Gen-4.5</strong>, released December 2025, which added native text-to-video generation on top of the image-conditioned workflow introduced in Gen-4 (March 2025).</li>
<li>Earlier overviews of this space (including the source material this notebook was built from) describe Runway at the <strong>Gen-2</strong> stage, which is now three major generations behind.</li>
<li>The general category description in the table — “text- and image-conditioned video generation” — still holds without modification; only a specific version number would need updating.</li>
</ul>
<p>This illustrates the intended use of the caution note attached to the table: the category-level description was written to survive this kind of check, while any row that had included a specific version number would already need a correction after roughly a year.</p>


</section>
</section>

 ]]></description>
  <guid>https://bntechie.github.io/tutorials/promt_engineering/genai-prompt-engineering-tutorial.html</guid>
  <pubDate>Mon, 03 Aug 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/promt_engineering/images/prompt-engineering-funnel.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>The barbeque question: will AI’s data center problem end like the genome did?</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/AI_humanGenome/the-barbeque-question.html</link>
  <description><![CDATA[ 




<p>It happened somewhere between the second batch of skewers and the point where someone finally admitted the coals needed more time. Someone at the table—half paying attention to the grill, half to the group—said the thing that derailed the evening in the best way:</p>
<p><em>“You know, twenty years ago, sequencing a single human genome felt impossible. Now it’s routine. Is AI’s data center problem going to go the same way?”</em></p>
<p>Forks paused. It was a good question, the kind that sounds simple until you actually try to answer it.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/AI_humanGenome/illustration.png" class="img-fluid figure-img" style="width:90.0%" alt="Illustration of a grill with smoke rising into a DNA helix and server racks, symbolizing the genome sequencing and AI compute comparison"></p>
<figcaption>Smoke from a barbeque grill splitting into a DNA double helix on one side and a stack of data center server racks on the other</figcaption>
</figure>
</div>
<section id="the-3-billion-genome" class="level2">
<h2 class="anchored" data-anchor-id="the-3-billion-genome">The $3 Billion Genome</h2>
<p>Rewind to 2003. The Human Genome Project had just wrapped after thirteen years and roughly <strong>$3 billion</strong>, reading out the three billion base pairs of human DNA one laborious Sanger-sequencing run at a time. It was a moonshot—international, decade-spanning, celebrated with press conferences.</p>
<p>Fast forward, and something remarkable happened to that cost curve. It didn’t just fall—it <em>collapsed</em>. Sequencing a human genome went from tens of millions of dollars to a few thousand, and today, in highly optimized settings, the cost is approaching only a few hundred dollars. That transformation didn’t happen because Sanger sequencing became incrementally better every year. It happened because the entire approach was reinvented. Next-generation sequencing arrived with a fundamentally different chemistry, reading millions of DNA fragments in parallel instead of one at a time. Genome sequencing didn’t simply become cheaper—it was <em>replaced by something fundamentally better</em>.</p>
<p>That was the story someone was telling around the grill. And the question hanging in the smoke was this:</p>
<p><strong>Is AI’s compute crunch waiting for its own next-generation sequencing moment?</strong></p>
</section>
<section id="the-electron-problem" class="level2">
<h2 class="anchored" data-anchor-id="the-electron-problem">The Electron Problem</h2>
<p>Here’s where the table split into two camps.</p>
<p>The optimists argued that something very genome-like is already happening in AI. Training costs aren’t falling simply because chips are getting faster—they’re falling because of genuine algorithmic breakthroughs. Over the past decade, researchers have repeatedly shown that smarter model architectures, improved optimization methods, and more efficient training strategies can dramatically reduce the amount of computation required to reach a given level of performance.</p>
<p>DeepSeek, for example, demonstrated that architectural redesign—not simply buying more GPUs—can substantially reduce training and inference costs while maintaining frontier-level capability. Hardware is evolving alongside these algorithms: every new generation of AI accelerators delivers meaningful improvements in throughput and energy efficiency, steadily pushing the cost of computation downward.</p>
<p>It sounds strikingly similar to the genome story: a stubborn bottleneck overcome not by brute force, but by better ideas.</p>
<p>Then the skeptic at the table—there’s always one—pointed out the catch, and it changed the entire shape of the discussion.</p>
<p><strong>A genome has a finish line.</strong></p>
<p>There are about three billion base pairs, full stop. Once sequencing became inexpensive, researchers didn’t need to read <em>more DNA</em> from each person—the computational target stayed fixed. Demand for sequencing certainly exploded, with millions of genomes now being sequenced around the world, but the amount of DNA contained in a human genome never changed. Every efficiency improvement made sequencing cheaper, faster, and more accessible without moving the goalposts.</p>
<p><strong>AI has no comparable finish line.</strong></p>
<p>When training becomes ten times cheaper, nobody simply trains yesterday’s model for one-tenth the cost and goes home. Instead, researchers build larger models, run more experiments, deploy more applications, and serve vastly more users. Economists have a name for this pattern: <strong>Jevons Paradox</strong>. Making something more efficient often doesn’t reduce total consumption—it increases it, because lower cost creates entirely new uses that were previously impractical.</p>
<p>Industry analysis increasingly points in this direction. Efficiency gains in AI are likely to be accompanied by an explosion in experimentation, deployment, and inference at scale. Even if each unit of computation becomes cheaper, the total demand for computation may continue to grow.</p>
<p>There’s another wrinkle as well.</p>
<p>Genome sequencing benefited from a paradigm shift that fundamentally replaced the previous technology. Modern computing also experienced enormous efficiency gains during the cloud-computing revolution, when organizations moved workloads from inefficient on-premises server rooms into highly optimized hyperscale data centers.</p>
<p>Frontier AI, however, largely begins inside those already-optimized facilities. The easy infrastructure gains have mostly been captured before today’s AI boom. The next improvements must come from genuinely harder engineering problems: better chip architectures, smarter model designs, improved scheduling, higher hardware utilization, more efficient networking, advanced cooling, and entirely new approaches to computation itself.</p>
</section>
<section id="so-same-story-or-different-one" class="level2">
<h2 class="anchored" data-anchor-id="so-same-story-or-different-one">So, Same Story or Different One?</h2>
<p>By the time the coals were dying down, the table had more or less landed here: the mechanism rhymes.</p>
<p>Paradigm-breaking innovations—not incremental scaling—are what truly bend cost curves. AI is already experiencing several of them through new architectures, sparse models, improved training methods, specialized hardware, and increasingly sophisticated software engineering. In that sense, the genome story is repeating.</p>
<p>But the ending may be very different.</p>
<p>Genome sequencing is fundamentally a <strong>fixed-length problem</strong>. Every human genome contains roughly the same amount of DNA to read. Intelligence, by contrast, is an <strong>open-ended problem</strong>. Every time AI becomes cheaper to train or deploy, researchers don’t simply stop. They build more capable systems, create entirely new applications, expand inference to billions of users, and tackle problems that previously seemed out of reach. The goalposts keep moving.</p>
<p>So the honest answer isn’t that AI will have one dramatic “next-generation sequencing” moment after which the data-center problem disappears.</p>
<p>It’s more likely that AI will experience <strong>many</strong> such moments. Each breakthrough will make computation dramatically more efficient than before. But unlike genome sequencing, those gains may be continually absorbed by expanding demand, leaving society with ever more capable AI systems—yet not necessarily fewer data centers.</p>
<p>Even researchers who study this professionally disagree about how the balance will play out. Some believe algorithmic innovation and specialized hardware will continue to outpace demand growth. Others argue that energy availability, manufacturing capacity, and physical limits on computing will eventually become the dominant constraints. The debate remains very much alive.</p>
<p>Which, if you think about it, is a pretty good note to end a barbeque conversation on: not a tidy answer, but a much better question than the one you started with.</p>
<hr>
<p><em>Written after (and inspired by) an actual argument over the grill about whether we’re solving AI’s biggest infrastructure problem—or simply discovering how big “solved” needs to become.</em></p>


</section>

 ]]></description>
  <guid>https://bntechie.github.io/tutorials/AI_humanGenome/the-barbeque-question.html</guid>
  <pubDate>Mon, 27 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Multivariate Concepts in Statistical Genetics: From LD Score Regression to Genomic SEM</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/multivariate_concepts/genomicSEM.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/multivariate_concepts/images/genomic-sem-factor.svg" alt="Path diagram of a Genomic SEM common factor model: a latent factor F1 with arrows loading onto four observed traits (MDD, PTSD, ALCH, ANX), each with its own residual variance" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The model this tutorial builds up to fitting: a single shared genetic factor F1, estimated not from individual-level data but from a genetic covariance matrix built out of GWAS summary statistics alone.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">Genomic SEM</span> <span class="tag">LDSC</span> <span class="tag">Structural Equation Modeling</span> <span class="tag">R</span></p>
</div>
<section id="multivariate-concepts-in-statistical-genetics" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Multivariate Concepts in Statistical Genetics</h1>
<p>In many areas of statistical genetics, we are not only interested in whether a single trait is heritable. We are also interested in whether multiple traits share part of their genetic architecture.</p>
<p>For example, psychiatric traits such as major depression, anxiety, post-traumatic stress disorder, alcohol use disorder, bipolar disorder, and schizophrenia are not genetically isolated. They often show genetic overlap. This means that some genetic variants may influence more than one phenotype.</p>
<p>This tutorial introduces the main multivariate concepts needed to understand Genomic SEM. We will move step by step from basic ideas such as polygenicity and LD Score Regression to genetic covariance, genetic correlation, genome-wide structural models, and multivariate GWAS.</p>
<section id="why-do-we-need-multivariate-genetic-models" class="level3" data-number="1.0.1">
<h3 data-number="1.0.1" class="anchored" data-anchor-id="why-do-we-need-multivariate-genetic-models"><span class="header-section-number">1.0.1</span> 1. Why Do We Need Multivariate Genetic Models?</h3>
<p>Complex traits are usually highly polygenic. This means that they are influenced by thousands of genetic variants, each with a very small effect.</p>
<p>A simple single-gene model is usually not appropriate for complex psychiatric or behavioral traits. Instead, risk emerges from the combined effect of many variants.</p>
<p>This creates two important problems:</p>
<ol type="1">
<li>We need methods that can summarize genome-wide genetic signal.</li>
<li>We need methods that can estimate how much genetic signal is shared across traits.</li>
</ol>
<p>This is where LD Score Regression and Genomic SEM become useful.</p>
</section>
<section id="from-genetic-overlap-to-genetic-architecture" class="level3" data-number="1.0.2">
<h3 data-number="1.0.2" class="anchored" data-anchor-id="from-genetic-overlap-to-genetic-architecture"><span class="header-section-number">1.0.2</span> 2. From Genetic Overlap to Genetic Architecture</h3>
<p>Genetic overlap means that the same genetic variants contribute to variation in more than one phenotype.</p>
<p>However, genetic overlap can appear in different forms.</p>
<p>Two traits may share:</p>
<p>A broad common genetic factor Several smaller domain-specific factors A mixture of shared and trait-specific genetic effects SNPs that influence one trait much more than another</p>
<p>Genomic SEM allows us to model these possibilities explicitly.</p>
<p>For example, if four psychiatric traits are genetically correlated, we can test whether this correlation is well explained by one common factor.</p>
<p>A simplified model could be:</p>
<p>$ F_1 MDD, PTSD, ANX, ALCH $</p>
<p>where <img src="https://latex.codecogs.com/png.latex?(F_1)"> is a shared genetic liability factor.</p>
</section>
<section id="why-traits-do-not-need-to-come-from-the-same-sample" class="level3" data-number="1.0.3">
<h3 data-number="1.0.3" class="anchored" data-anchor-id="why-traits-do-not-need-to-come-from-the-same-sample"><span class="header-section-number">1.0.3</span> 3. Why Traits Do Not Need to Come From the Same Sample</h3>
<p>One powerful feature of LD Score Regression and Genomic SEM is that traits do not need to be measured in the same individuals.</p>
<p>For example, we may have:</p>
<p>A GWAS of major depression from one cohort A GWAS of anxiety from another cohort A GWAS of PTSD from another cohort A GWAS of alcohol use disorder from another cohort</p>
<p>These GWAS may come from different studies, different consortia, and different individuals.</p>
<p>The connection between them is the genome.</p>
<p>Because each GWAS reports SNP-level effects across the genome, we can compare the pattern of SNP effects across traits. If SNPs that increase one trait also tend to increase another trait, this creates evidence of shared genetic architecture.</p>
<p>This is why summary statistics are so useful. We do not always need access to individual-level data to study genetic overlap.</p>
</section>
<section id="polygenicity-and-linkage-disequilibrium" class="level3" data-number="1.0.4">
<h3 data-number="1.0.4" class="anchored" data-anchor-id="polygenicity-and-linkage-disequilibrium"><span class="header-section-number">1.0.4</span> 2. Polygenicity and Linkage Disequilibrium</h3>
<p>Suppose a phenotype is influenced by a few true causal variants. In GWAS, we do not observe only those causal variants. We also observe many nearby SNPs that are correlated with them.</p>
<p>This correlation among SNPs is called linkage disequilibrium, or LD.</p>
<p>A SNP with high LD is correlated with many nearby SNPs. Therefore, high-LD SNPs are more likely to tag causal variants. This means they are more likely to show association signal even if they are not causal themselves.</p>
<section id="ld-score" class="level4" data-number="1.0.4.1">
<h4 data-number="1.0.4.1" class="anchored" data-anchor-id="ld-score"><span class="header-section-number">1.0.4.1</span> 2.1 LD Score</h4>
<p>The LD score of SNP (j) is defined as:</p>
<p>$ _j = <em>i r</em>{ij}^2 $</p>
<p>where:</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?%5Cell_j"> is the LD score of SNP (j)</li>
<li><img src="https://latex.codecogs.com/png.latex?r_%7Bij%7D%5E2"> is the squared correlation between SNP (i) and SNP (j)</li>
</ul>
<p>A high LD score means that the SNP is correlated with many other SNPs.</p>
</section>
</section>
<section id="the-intuition-behind-ld-score-regression" class="level3" data-number="1.0.5">
<h3 data-number="1.0.5" class="anchored" data-anchor-id="the-intuition-behind-ld-score-regression"><span class="header-section-number">1.0.5</span> 4. The Intuition Behind LD Score Regression</h3>
<p>LD Score Regression works because highly polygenic traits create a predictable relationship between LD and GWAS signal.</p>
<p>Imagine there are true causal variants in the genome.</p>
<p>A SNP does not need to be causal to show association. If it is correlated with a causal variant through LD, it can still pick up association signal.</p>
<p>This means:</p>
<p>High-LD SNPs are correlated with many nearby SNPs. Therefore, they have more chances to tag causal variants. Low-LD SNPs are correlated with fewer nearby SNPs. Therefore, they usually only show strong signal if they are causal or very close to causal variants.</p>
<p>For a highly polygenic trait, many causal variants are spread across the genome. As a result, SNPs with higher LD scores tend to have larger GWAS chi-square statistics on average.</p>
<p>This is the core logic of LD Score Regression.</p>
</section>
<section id="why-the-ldsc-intercept-matters" class="level3" data-number="1.0.6">
<h3 data-number="1.0.6" class="anchored" data-anchor-id="why-the-ldsc-intercept-matters"><span class="header-section-number">1.0.6</span> 5. Why the LDSC Intercept Matters</h3>
<p>In GWAS, test statistics can be inflated for several reasons.</p>
<p>Some inflation reflects true polygenic signal. This is expected when many SNPs contribute to the trait.</p>
<p>However, some inflation can come from confounding, such as:</p>
<p>Population stratification Cryptic relatedness Sample overlap Technical artifacts</p>
<p>LD Score Regression separates these components.</p>
<p>The slope of the regression captures polygenic signal.</p>
<p>The intercept captures inflation that is not explained by LD score.</p>
<p>This is why LD Score Regression is useful: it helps distinguish true polygenic signal from confounding.</p>
</section>
<section id="snp-heritability-using-ld-score-regression" class="level3" data-number="1.0.7">
<h3 data-number="1.0.7" class="anchored" data-anchor-id="snp-heritability-using-ld-score-regression"><span class="header-section-number">1.0.7</span> 3. SNP Heritability Using LD Score Regression</h3>
<p>LD Score Regression is based on a simple idea:</p>
<p>If a trait is highly polygenic, SNPs with higher LD scores should, on average, have larger GWAS test statistics.</p>
<p>In other words, we regress the GWAS chi-square statistics on LD scores.</p>
<p>The expected chi-square statistic for SNP (j) can be written as:</p>
<p>$ E[_j^2 | _j] = _j + Na + 1 $</p>
<p>where:</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?N"> is the GWAS sample size</li>
<li><img src="https://latex.codecogs.com/png.latex?h%5E2"> is SNP heritability</li>
<li><img src="https://latex.codecogs.com/png.latex?M"> is the number of SNPs</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Cell_j"> is the LD score</li>
<li><img src="https://latex.codecogs.com/png.latex?a"> captures confounding such as population stratification</li>
<li>the intercept captures inflation not due to polygenic signal</li>
</ul>
<p>The slope of this regression is used to estimate SNP heritability.</p>
<section id="why-sample-size-matters" class="level4" data-number="1.0.7.1">
<h4 data-number="1.0.7.1" class="anchored" data-anchor-id="why-sample-size-matters"><span class="header-section-number">1.0.7.1</span> 3.1 Why Sample Size Matters</h4>
<p>Imagine two traits have the same GWAS p-values, but different sample sizes:</p>
<ul>
<li>Trait 1: <img src="https://latex.codecogs.com/png.latex?N%20=%2050,000"></li>
<li>Trait 2: <img src="https://latex.codecogs.com/png.latex?N%20=%20100,000"></li>
</ul>
<p>If the association statistics are similar, the trait with the smaller sample size may imply stronger per-sample genetic signal. This is why LD Score Regression accounts for sample size when estimating heritability.</p>
</section>
</section>
<section id="genetic-covariance-and-genetic-correlation" class="level3" data-number="1.0.8">
<h3 data-number="1.0.8" class="anchored" data-anchor-id="genetic-covariance-and-genetic-correlation"><span class="header-section-number">1.0.8</span> 4. Genetic Covariance and Genetic Correlation</h3>
<p>LD Score Regression can also be extended to two traits.</p>
<p>Instead of regressing one trait’s chi-square statistics on LD scores, we examine the product of GWAS (Z)-statistics across two traits.</p>
<p>For traits (Y_1) and (Y_2), we use:</p>
<p>$ Z_{1j}Z_{2j} $</p>
<p>If SNPs with high LD scores tend to have similar effects across both traits, this suggests genetic overlap.</p>
<section id="genetic-covariance" class="level4" data-number="1.0.8.1">
<h4 data-number="1.0.8.1" class="anchored" data-anchor-id="genetic-covariance"><span class="header-section-number">1.0.8.1</span> 4.1 Genetic Covariance</h4>
<p>Genetic covariance measures the extent to which two traits share genetic influences.</p>
<p>The cross-trait LD Score Regression equation is:</p>
<p>$ E[z_{1j}z_{2j}|_j] = <em>j + + </em>{Ns} $</p>
<p>Conceptually:</p>
<ul>
<li>The slope estimates genetic covariance.</li>
<li>The intercept captures sample overlap and confounding.</li>
<li>Traits do not need to be measured in the same individuals.</li>
</ul>
<p>This is very useful because many GWAS summary statistics are publicly available and come from independent cohorts.</p>
</section>
<section id="genetic-correlation" class="level4" data-number="1.0.8.2">
<h4 data-number="1.0.8.2" class="anchored" data-anchor-id="genetic-correlation"><span class="header-section-number">1.0.8.2</span> 4.2 Genetic Correlation</h4>
<p>Genetic correlation is the standardized form of genetic covariance:</p>
<p>$ r_g = {} $</p>
<p>A genetic correlation close to 1 means two traits share much of their genetic architecture.</p>
<p>A genetic correlation close to 0 means little shared genetic influence.</p>
<p>A negative genetic correlation means genetic variants that increase one trait tend to decrease the other.</p>
</section>
</section>
<section id="why-shared-genetic-architecture-requires-new-models" class="level3" data-number="1.0.9">
<h3 data-number="1.0.9" class="anchored" data-anchor-id="why-shared-genetic-architecture-requires-new-models"><span class="header-section-number">1.0.9</span> 8. Why Shared Genetic Architecture Requires New Models</h3>
</section>
<section id="from-ld-score-regression-to-genomic-sem" class="level3" data-number="1.0.10">
<h3 data-number="1.0.10" class="anchored" data-anchor-id="from-ld-score-regression-to-genomic-sem"><span class="header-section-number">1.0.10</span> 5. From LD Score Regression to Genomic SEM</h3>
<p>Genomic SEM stands for Genomic Structural Equation Modeling.</p>
<p>It provides a flexible framework for fitting structural equation models to genetic covariance matrices estimated from GWAS summary statistics.</p>
<p>The main advantage is that we can model genetic relationships among traits even when those traits were measured in different samples.</p>
</section>
<section id="the-two-stage-framework-of-genomic-sem" class="level3" data-number="1.0.11">
<h3 data-number="1.0.11" class="anchored" data-anchor-id="the-two-stage-framework-of-genomic-sem"><span class="header-section-number">1.0.11</span> 6. The Two-Stage Framework of Genomic SEM</h3>
<p>Genomic SEM has two main stages.</p>
<section id="stage-1-estimate-genetic-covariance-structure" class="level4" data-number="1.0.11.1">
<h4 data-number="1.0.11.1" class="anchored" data-anchor-id="stage-1-estimate-genetic-covariance-structure"><span class="header-section-number">1.0.11.1</span> Stage 1: Estimate Genetic Covariance Structure</h4>
<p>Using multivariable LD Score Regression, we estimate:</p>
<ol type="1">
<li>A genetic covariance matrix</li>
<li>A sampling covariance matrix</li>
</ol>
<p>The genetic covariance matrix is usually called (S).</p>
<p>The diagonal elements of (S) are SNP heritabilities.</p>
<p>The off-diagonal elements are genetic covariances.</p>
<p>A simplified matrix looks like this:</p>
$ S =
<img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bbmatrix%7D%0Ah%5E2_1%20&amp;%20cov_%7Bg,12%7D%20&amp;%20cov_%7Bg,13%7D%20%5C%5C%0Acov_%7Bg,12%7D%20&amp;%20h%5E2_2%20&amp;%20cov_%7Bg,23%7D%20%5C%5C%0Acov_%7Bg,13%7D%20&amp;%20cov_%7Bg,23%7D%20&amp;%20h%5E2_3%0A%5Cend%7Bbmatrix%7D">
<p>$</p>
</section>
<section id="stage-2-fit-a-structural-equation-model" class="level4" data-number="1.0.11.2">
<h4 data-number="1.0.11.2" class="anchored" data-anchor-id="stage-2-fit-a-structural-equation-model"><span class="header-section-number">1.0.11.2</span> Stage 2: Fit a Structural Equation Model</h4>
<p>After estimating (S), we fit a model to explain the covariance structure.</p>
<p>For example, we may fit a common factor model where depression, anxiety, PTSD, and alcohol use disorder load on a shared internalizing factor.</p>
</section>
</section>
<section id="genome-wide-sem-vs-multivariate-gwas" class="level3" data-number="1.0.12">
<h3 data-number="1.0.12" class="anchored" data-anchor-id="genome-wide-sem-vs-multivariate-gwas"><span class="header-section-number">1.0.12</span> 9. Genome-Wide SEM vs Multivariate GWAS</h3>
<p>It is important to distinguish between genome-wide SEM and multivariate GWAS.</p>
<section id="genome-wide-sem" class="level4" data-number="1.0.12.1">
<h4 data-number="1.0.12.1" class="anchored" data-anchor-id="genome-wide-sem"><span class="header-section-number">1.0.12.1</span> Genome-Wide SEM</h4>
<p>Genome-wide SEM uses the genetic covariance matrix across traits.</p>
<p>It asks:</p>
<p>What is the genetic relationship among these traits?</p>
<p>For example:</p>
<p>Do the traits load on one common factor? Are there multiple factors? Does one genetic trait predict another? How well does the model fit?</p>
<p>This stage does not test SNP effects directly.</p>
</section>
<section id="multivariate-gwas" class="level4" data-number="1.0.12.2">
<h4 data-number="1.0.12.2" class="anchored" data-anchor-id="multivariate-gwas"><span class="header-section-number">1.0.12.2</span> Multivariate GWAS</h4>
<p>Multivariate GWAS adds SNP effects to the model.</p>
<p>It asks:</p>
<p>Which SNPs are associated with the latent genetic factor?</p>
<p>For example:</p>
<p>$ F_1 SNP $</p>
<p>This tests whether each SNP predicts the shared genetic factor.</p>
<p>So, genome-wide SEM models the covariance structure, while multivariate GWAS tests SNP-level effects on that structure.</p>
</section>
</section>
<section id="practical-setup-in-r" class="level3" data-number="1.0.13">
<h3 data-number="1.0.13" class="anchored" data-anchor-id="practical-setup-in-r"><span class="header-section-number">1.0.13</span> 7. Practical Setup in R</h3>
<p>We will now follow the practical structure from the workshop.</p>
<p>The main steps are:</p>
<ol type="1">
<li>Load GenomicSEM</li>
<li>Munge GWAS summary statistics</li>
<li>Run LD Score Regression</li>
<li>Specify and run a genome-wide Genomic SEM model</li>
<li>Prepare summary statistics for multivariate GWAS</li>
<li>Run userGWAS</li>
<li>Interpret factor GWAS and QSNP results</li>
</ol>
<div id="87b036b1-bd5f-4445-b506-b28caf101862" class="cell" data-execution_count="14">
<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;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"devtools"</span>)</span>
<span id="cb1-2"></span>
<span id="cb1-3">devtools<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;">install_github</span>(</span>
<span id="cb1-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GenomicSEM/GenomicSEM"</span></span>
<span id="cb1-5">)</span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load GenomicSEM</span></span>
<span id="cb1-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">require</span>(GenomicSEM)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
The downloaded binary packages are in
    /var/folders/3f/6pzn2nyn32d7wthyxkzsqyxcdrtvym/T//RtmpPbLU4V/downloaded_packages</code></pre>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>rlang        (1.1.6  -&gt; 1.2.0    ) [CRAN]
lifecycle    (1.0.4  -&gt; 1.0.5    ) [CRAN]
glue         (1.8.0  -&gt; 1.8.1    ) [CRAN]
cli          (3.6.5  -&gt; 3.6.6    ) [CRAN]
vctrs        (0.6.5  -&gt; 0.7.3    ) [CRAN]
utf8         (1.2.5  -&gt; 1.2.6    ) [CRAN]
pillar       (1.10.2 -&gt; 1.11.1   ) [CRAN]
magrittr     (2.0.3  -&gt; 2.0.5    ) [CRAN]
cpp11        (0.5.2  -&gt; 0.5.5    ) [CRAN]
bit          (4.0.5  -&gt; 4.6.0    ) [CRAN]
tzdb         (0.4.0  -&gt; 0.5.0    ) [CRAN]
tibble       (3.2.1  -&gt; 3.3.1    ) [CRAN]
hms          (1.1.3  -&gt; 1.1.4    ) [CRAN]
bit64        (4.0.5  -&gt; 4.8.2    ) [CRAN]
colorspace   (2.1-1  -&gt; 2.1-2    ) [CRAN]
gridBase     (NA     -&gt; 0.4-7    ) [CRAN]
sfsmisc      (NA     -&gt; 1.1-24   ) [CRAN]
R.oo         (1.26.0 -&gt; 1.27.1   ) [CRAN]
data.table   (1.17.4 -&gt; 1.18.4   ) [CRAN]
mnormt       (2.1.1  -&gt; 2.1.2    ) [CRAN]
vroom        (1.6.5  -&gt; 1.7.1    ) [CRAN]
clipr        (0.8.0  -&gt; 0.8.1    ) [CRAN]
proxy        (0.4-27 -&gt; 0.4-29   ) [CRAN]
Rcpp         (1.0.14 -&gt; 1.1.1-1.1) [CRAN]
simsalapar   (NA     -&gt; 1.0-13   ) [CRAN]
mgsub        (NA     -&gt; 2.0.0    ) [CRAN]
dplyr        (1.1.4  -&gt; 1.2.1    ) [CRAN]
R.utils      (2.12.3 -&gt; 2.13.0   ) [CRAN]
splitstac... (NA     -&gt; 1.4.8.1  ) [CRAN]
stringr      (1.5.1  -&gt; 1.6.0    ) [CRAN]
lavaan       (0.6-19 -&gt; 0.6-21   ) [CRAN]
gdata        (3.0.0  -&gt; 3.0.1    ) [CRAN]
readr        (2.1.5  -&gt; 2.2.0    ) [CRAN]
e1071        (1.7-14 -&gt; 1.7-17   ) [CRAN]</code></pre>
</div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre>The downloaded binary packages are in

    /var/folders/3f/6pzn2nyn32d7wthyxkzsqyxcdrtvym/T//RtmpPbLU4V/downloaded_packages

<span class="ansi-cyan-fg">──</span> <span class="ansi-cyan-fg">R CMD build</span> <span class="ansi-cyan-fg">─────────────────────────────────────────────────────────────────</span>

<span class="ansi-green-fg">✔</span>  <span class="ansi-bright-black-fg">checking for file ‘/private/var/folders/3f/6pzn2nyn32d7wthyxkzsqyxcdrtvym/T/RtmpPbLU4V/remotes2dbf3fb76124/GenomicSEM-GenomicSEM-0a63ac0/DESCRIPTION’</span>

<span class="ansi-bright-black-fg">─</span><span class="ansi-bright-black-fg">  </span><span class="ansi-bright-black-fg">preparing ‘GenomicSEM’:</span>

<span class="ansi-green-fg">✔</span>  <span class="ansi-bright-black-fg">checking DESCRIPTION meta-information</span>

<span class="ansi-bright-black-fg">─</span><span class="ansi-bright-black-fg">  </span><span class="ansi-bright-black-fg">excluding invalid files</span>

   Subdirectory 'man' contains invalid file names:

     ‘decisiontree.png’

<span class="ansi-bright-black-fg">─</span><span class="ansi-bright-black-fg">  </span><span class="ansi-bright-black-fg">checking for LF line-endings in source and make files and shell scripts</span>

<span class="ansi-bright-black-fg">─</span><span class="ansi-bright-black-fg">  </span><span class="ansi-bright-black-fg">checking for empty or unneeded directories</span>

   Omitted ‘LazyData’ from DESCRIPTION

<span class="ansi-bright-black-fg">─</span><span class="ansi-bright-black-fg">  </span><span class="ansi-bright-black-fg">building ‘GenomicSEM_0.0.5.tar.gz’</span>

   Warning: invalid uid value replaced by that for user 'nobody'

   Warning: invalid gid value replaced by that for user 'nobody'

   


</pre>
</div>
</div>
</div>
<div id="9ba6f678-e100-4eaa-a9b6-81c2ba60a044" class="cell" data-execution_count="15">
<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;">library</span>(GenomicSEM)</span></code></pre></div></div>
</div>
</section>
<section id="step-1-munge-summary-statistics" class="level3" data-number="1.0.14">
<h3 data-number="1.0.14" class="anchored" data-anchor-id="step-1-munge-summary-statistics"><span class="header-section-number">1.0.14</span> 8. Step 1: Munge Summary Statistics</h3>
<p>Munging is the process of cleaning and harmonizing GWAS summary statistics.</p>
<p>It usually includes:</p>
<ul>
<li>Aligning alleles</li>
<li>Filtering to HapMap3 SNPs</li>
<li>Checking SNP IDs</li>
<li>Formatting effect sizes</li>
<li>Formatting standard errors</li>
<li>Preparing files for LD Score Regression</li>
</ul>
<p>In this practical, the workshop uses four traits:</p>
<ul>
<li>ALCH: Alcohol use disorder</li>
<li>PTSD: Post-traumatic stress disorder</li>
<li>MDD: Major depressive disorder</li>
<li>ANX: Anxiety disorder</li>
</ul>
<div id="6526efce-66b8-480d-b325-7d65f8794fc1" class="cell" data-execution_count="16">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Example file names</span></span>
<span id="cb5-2">files <span class="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>
<span id="cb5-3">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ALCH_withrsID.txt"</span>,</span>
<span id="cb5-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SORTED_PTSD_EA9_ALL_study_specific_PCs1.txt"</span>,</span>
<span id="cb5-5">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MDD_withNeff.txt"</span>,</span>
<span id="cb5-6">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ANX_withNeff.txt"</span></span>
<span id="cb5-7">)</span>
<span id="cb5-8"></span>
<span id="cb5-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># HapMap3 SNP reference file</span></span>
<span id="cb5-10">hm3 <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;">"eur_w_ld_chr/w_hm3.snplist"</span></span>
<span id="cb5-11"></span>
<span id="cb5-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Trait names</span></span>
<span id="cb5-13">trait.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;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ALCH"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PTSD"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MDD"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ANX"</span>)</span>
<span id="cb5-14"></span>
<span id="cb5-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Effective sample size</span></span>
<span id="cb5-16">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;">c</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5831.346</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>)</span>
<span id="cb5-17"></span>
<span id="cb5-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run munge</span></span>
<span id="cb5-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This is commented out because the workshop already provides prepared files.</span></span>
<span id="cb5-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># munge(files = files, hm3 = hm3, trait.names = trait.names, N = N)</span></span></code></pre></div></div>
</div>
</section>
<section id="step-2-run-multivariable-ld-score-regression" class="level3" data-number="1.0.15">
<h3 data-number="1.0.15" class="anchored" data-anchor-id="step-2-run-multivariable-ld-score-regression"><span class="header-section-number">1.0.15</span> 9. Step 2: Run Multivariable LD Score Regression</h3>
<p>After munging, we run LD Score Regression.</p>
<p>This estimates:</p>
<ul>
<li>SNP heritability for each trait</li>
<li>Genetic covariance between traits</li>
<li>Genetic correlation between traits</li>
<li>Sampling covariance matrix</li>
</ul>
<p>The output is later used by Genomic SEM.</p>
<div id="8dcd0581-faac-4881-a25a-9c2743b09ffe" class="cell" data-execution_count="17">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Munged summary statistics</span></span>
<span id="cb6-2">traits <span class="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>
<span id="cb6-3">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ALCH.sumstats.gz"</span>,</span>
<span id="cb6-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PTSD.sumstats.gz"</span>,</span>
<span id="cb6-5">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MDD.sumstats.gz"</span>,</span>
<span id="cb6-6">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ANX.sumstats.gz"</span></span>
<span id="cb6-7">)</span>
<span id="cb6-8"></span>
<span id="cb6-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample prevalence</span></span>
<span id="cb6-10">sample.prev <span class="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;">5</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;">5</span>, .<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb6-11"></span>
<span id="cb6-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Population prevalence</span></span>
<span id="cb6-13">population.prev <span class="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;">159</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;">15</span>, .<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb6-14"></span>
<span id="cb6-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># LD score folders</span></span>
<span id="cb6-16">ld <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;">"eur_w_ld_chr/"</span></span>
<span id="cb6-17">wld <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;">"eur_w_ld_chr/"</span></span>
<span id="cb6-18"></span>
<span id="cb6-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Trait names</span></span>
<span id="cb6-20">trait.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;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ALCH"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PTSD"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MDD"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ANX"</span>)</span>
<span id="cb6-21"></span>
<span id="cb6-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run LDSC</span></span>
<span id="cb6-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This is commented out because the workshop provides LDSC_INT.RData.</span></span>
<span id="cb6-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># LDSC_INT &lt;- ldsc(</span></span>
<span id="cb6-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   traits = traits,</span></span>
<span id="cb6-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   sample.prev = sample.prev,</span></span>
<span id="cb6-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   population.prev = population.prev,</span></span>
<span id="cb6-28"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   ld = ld,</span></span>
<span id="cb6-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   wld = wld,</span></span>
<span id="cb6-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   trait.names = trait.names</span></span>
<span id="cb6-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># )</span></span>
<span id="cb6-32"></span>
<span id="cb6-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save LDSC output</span></span>
<span id="cb6-34"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># save(LDSC_INT, file = "LDSC_INT.RData")</span></span></code></pre></div></div>
</div>
</section>
<section id="step-3-load-the-ldsc-output" class="level3" data-number="1.0.16">
<h3 data-number="1.0.16" class="anchored" data-anchor-id="step-3-load-the-ldsc-output"><span class="header-section-number">1.0.16</span> 10. Step 3: Load the LDSC Output</h3>
<p>The workshop practical already provides the LDSC object.</p>
<p>This object contains the genetic covariance matrix and sampling covariance matrix.</p>
<div id="1fdb33fb-e2c0-4012-9bc8-b25218cec072" class="cell" data-execution_count="18">
<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;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LDSC_INT.RData"</span>)</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Genetic covariance matrix</span></span>
<span id="cb7-4">LDSC_INT<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>S</span>
<span id="cb7-5"></span>
<span id="cb7-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sampling covariance matrix</span></span>
<span id="cb7-7">LDSC_INT<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>V</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 4 × 4 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">ALCH</th>
<th data-quarto-table-cell-role="th" scope="col">PTSD</th>
<th data-quarto-table-cell-role="th" scope="col">MDD</th>
<th data-quarto-table-cell-role="th" scope="col">ANX</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0.13938790</td>
<td>0.05977947</td>
<td>0.05943021</td>
<td>0.08500236</td>
</tr>
<tr class="even">
<td>0.05977947</td>
<td>0.23937808</td>
<td>0.05799439</td>
<td>0.11428679</td>
</tr>
<tr class="odd">
<td>0.05943021</td>
<td>0.05799439</td>
<td>0.08503281</td>
<td>0.12667327</td>
</tr>
<tr class="even">
<td>0.08500236</td>
<td>0.11428679</td>
<td>0.12667327</td>
<td>0.23329361</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 10 × 10 of type dbl</caption>
<tbody>
<tr class="odd">
<td>6.041603e-04</td>
<td>4.630259e-05</td>
<td>1.329209e-05</td>
<td>2.110818e-05</td>
<td>1.699375e-04</td>
<td>1.928842e-05</td>
<td>5.939947e-06</td>
<td>3.078558e-06</td>
<td>6.866515e-06</td>
<td>1.292371e-05</td>
</tr>
<tr class="even">
<td>4.630259e-05</td>
<td>1.683117e-03</td>
<td>5.491624e-06</td>
<td>1.012613e-04</td>
<td>7.541207e-05</td>
<td>1.794540e-05</td>
<td>9.955430e-05</td>
<td>2.224531e-07</td>
<td>3.119102e-06</td>
<td>1.406092e-05</td>
</tr>
<tr class="odd">
<td>1.329209e-05</td>
<td>5.491624e-06</td>
<td>3.692467e-05</td>
<td>4.865869e-05</td>
<td>8.966010e-05</td>
<td>1.773068e-06</td>
<td>2.035833e-05</td>
<td>6.028298e-06</td>
<td>9.777927e-06</td>
<td>7.764292e-06</td>
</tr>
<tr class="even">
<td>2.110818e-05</td>
<td>1.012613e-04</td>
<td>4.865869e-05</td>
<td>2.627033e-04</td>
<td>1.244898e-05</td>
<td>-7.693747e-08</td>
<td>1.510451e-05</td>
<td>6.091000e-06</td>
<td>1.858721e-05</td>
<td>3.524720e-05</td>
</tr>
<tr class="odd">
<td>1.699375e-04</td>
<td>7.541207e-05</td>
<td>8.966010e-05</td>
<td>1.244898e-05</td>
<td>1.135989e-02</td>
<td>4.536925e-05</td>
<td>3.350365e-04</td>
<td>-1.606011e-05</td>
<td>5.419991e-05</td>
<td>1.212088e-06</td>
</tr>
<tr class="even">
<td>1.928842e-05</td>
<td>1.794540e-05</td>
<td>1.773068e-06</td>
<td>-7.693747e-08</td>
<td>4.536925e-05</td>
<td>1.336556e-04</td>
<td>1.255636e-04</td>
<td>7.752931e-06</td>
<td>1.314640e-05</td>
<td>3.972090e-05</td>
</tr>
<tr class="odd">
<td>5.939947e-06</td>
<td>9.955430e-05</td>
<td>2.035833e-05</td>
<td>1.510451e-05</td>
<td>3.350365e-04</td>
<td>1.255636e-04</td>
<td>8.250458e-04</td>
<td>-4.762316e-07</td>
<td>5.242814e-06</td>
<td>3.447767e-05</td>
</tr>
<tr class="even">
<td>3.078558e-06</td>
<td>2.224531e-07</td>
<td>6.028298e-06</td>
<td>6.091000e-06</td>
<td>-1.606011e-05</td>
<td>7.752931e-06</td>
<td>-4.762316e-07</td>
<td>1.219319e-05</td>
<td>1.921343e-05</td>
<td>1.590191e-05</td>
</tr>
<tr class="odd">
<td>6.866515e-06</td>
<td>3.119102e-06</td>
<td>9.777927e-06</td>
<td>1.858721e-05</td>
<td>5.419991e-05</td>
<td>1.314640e-05</td>
<td>5.242814e-06</td>
<td>1.921343e-05</td>
<td>5.109221e-05</td>
<td>5.444954e-05</td>
</tr>
<tr class="even">
<td>1.292371e-05</td>
<td>1.406092e-05</td>
<td>7.764292e-06</td>
<td>3.524720e-05</td>
<td>1.212088e-06</td>
<td>3.972090e-05</td>
<td>3.447767e-05</td>
<td>1.590191e-05</td>
<td>5.444954e-05</td>
<td>2.843342e-04</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="understanding-the-genetic-covariance-matrix" class="level3" data-number="1.0.17">
<h3 data-number="1.0.17" class="anchored" data-anchor-id="understanding-the-genetic-covariance-matrix"><span class="header-section-number">1.0.17</span> 11. Understanding the Genetic Covariance Matrix</h3>
<p>The matrix <code>LDSC_INT$S</code> contains genetic variances and covariances.</p>
<p>The diagonal values are SNP heritabilities.</p>
<p>The off-diagonal values are genetic covariances.</p>
<p>For example, if the covariance between MDD and ANX is high, this suggests that depression and anxiety share genetic influences.</p>
<div id="eae10bd9-67e8-4b21-bb1f-dc468b047775" class="cell" data-execution_count="19">
<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;"># Print genetic covariance matrix</span></span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(LDSC_INT<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>S)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>           ALCH       PTSD        MDD        ANX
[1,] 0.13938790 0.05977947 0.05943021 0.08500236
[2,] 0.05977947 0.23937808 0.05799439 0.11428679
[3,] 0.05943021 0.05799439 0.08503281 0.12667327
[4,] 0.08500236 0.11428679 0.12667327 0.23329361</code></pre>
</div>
</div>
</section>
<section id="understanding-the-sampling-covariance-matrix" class="level3" data-number="1.0.18">
<h3 data-number="1.0.18" class="anchored" data-anchor-id="understanding-the-sampling-covariance-matrix"><span class="header-section-number">1.0.18</span> 12. Understanding the Sampling Covariance Matrix</h3>
<p>The matrix <code>LDSC_INT$V</code> contains uncertainty around the estimates in <code>S</code>.</p>
<p>This is important because some GWAS are more highly powered than others.</p>
<p>It also models dependencies caused by sample overlap between GWAS studies.</p>
<div id="bc02db6b-7339-4bf0-83da-b7f515dfb66c" class="cell" data-execution_count="20">
<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;"># Print sampling covariance matrix</span></span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(LDSC_INT<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>V)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>              [,1]         [,2]         [,3]          [,4]          [,5]
 [1,] 6.041603e-04 4.630259e-05 1.329209e-05  2.110818e-05  1.699375e-04
 [2,] 4.630259e-05 1.683117e-03 5.491624e-06  1.012613e-04  7.541207e-05
 [3,] 1.329209e-05 5.491624e-06 3.692467e-05  4.865869e-05  8.966010e-05
 [4,] 2.110818e-05 1.012613e-04 4.865869e-05  2.627033e-04  1.244898e-05
 [5,] 1.699375e-04 7.541207e-05 8.966010e-05  1.244898e-05  1.135989e-02
 [6,] 1.928842e-05 1.794540e-05 1.773068e-06 -7.693747e-08  4.536925e-05
 [7,] 5.939947e-06 9.955430e-05 2.035833e-05  1.510451e-05  3.350365e-04
 [8,] 3.078558e-06 2.224531e-07 6.028298e-06  6.091000e-06 -1.606011e-05
 [9,] 6.866515e-06 3.119102e-06 9.777927e-06  1.858721e-05  5.419991e-05
[10,] 1.292371e-05 1.406092e-05 7.764292e-06  3.524720e-05  1.212088e-06
               [,6]          [,7]          [,8]         [,9]        [,10]
 [1,]  1.928842e-05  5.939947e-06  3.078558e-06 6.866515e-06 1.292371e-05
 [2,]  1.794540e-05  9.955430e-05  2.224531e-07 3.119102e-06 1.406092e-05
 [3,]  1.773068e-06  2.035833e-05  6.028298e-06 9.777927e-06 7.764292e-06
 [4,] -7.693747e-08  1.510451e-05  6.091000e-06 1.858721e-05 3.524720e-05
 [5,]  4.536925e-05  3.350365e-04 -1.606011e-05 5.419991e-05 1.212088e-06
 [6,]  1.336556e-04  1.255636e-04  7.752931e-06 1.314640e-05 3.972090e-05
 [7,]  1.255636e-04  8.250458e-04 -4.762316e-07 5.242814e-06 3.447767e-05
 [8,]  7.752931e-06 -4.762316e-07  1.219319e-05 1.921343e-05 1.590191e-05
 [9,]  1.314640e-05  5.242814e-06  1.921343e-05 5.109221e-05 5.444954e-05
[10,]  3.972090e-05  3.447767e-05  1.590191e-05 5.444954e-05 2.843342e-04</code></pre>
</div>
</div>
</section>
<section id="factor-identification-in-genomic-sem" class="level3" data-number="1.0.19">
<h3 data-number="1.0.19" class="anchored" data-anchor-id="factor-identification-in-genomic-sem"><span class="header-section-number">1.0.19</span> 10. Factor Identification in Genomic SEM</h3>
<p>Latent factors do not have a natural scale. Therefore, we must identify the scale of the factor.</p>
<p>There are two common approaches.</p>
<p>Option 1: Unit Variance Identification</p>
<p>In this approach, the variance of the latent factor is fixed to 1.</p>
<p>Example:</p>
<p>Model &lt;- ” F1 =~ NA<em>MDD + PTSD + ALCH + ANX F1 <sub></sub> 1</em>F1 ”</p>
<p>This means the factor has a standardized variance.</p>
<p>In Genomic SEM, this is often equivalent to using:</p>
<p>std.lv = TRUE Option 2: Unit Loading Identification</p>
<p>In this approach, one factor loading is fixed to 1.</p>
<p>Example:</p>
<p>Model &lt;- ” F1 =~ 1*MDD + PTSD + ALCH + ANX ”</p>
<p>Here, the scale of the factor is defined by MDD.</p>
<p>Both approaches are valid, but they lead to different parameter scaling. The interpretation of the model should always consider how the factor was identified.</p>
</section>
<section id="lavaan-model-syntax-used-in-genomic-sem" class="level3" data-number="1.0.20">
<h3 data-number="1.0.20" class="anchored" data-anchor-id="lavaan-model-syntax-used-in-genomic-sem"><span class="header-section-number">1.0.20</span> 13. Lavaan Model Syntax Used in Genomic SEM</h3>
<p>Genomic SEM uses lavaan-style model syntax.</p>
<p>Here are the most important operators:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Syntax</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>A ~ B</code></td>
<td>A is regressed on B</td>
</tr>
<tr class="even">
<td><code>A ~~ A</code></td>
<td>Variance of A</td>
</tr>
<tr class="odd">
<td><code>A ~~ B</code></td>
<td>Covariance between A and B</td>
</tr>
<tr class="even">
<td><code>F1 =~ A + B + C</code></td>
<td>Latent factor F1 loads on A, B, and C</td>
</tr>
<tr class="odd">
<td><code>A ~~ 1*B</code></td>
<td>Fix covariance between A and B to 1</td>
</tr>
<tr class="even">
<td><code>A ~~ a*B</code></td>
<td>Label covariance as parameter <code>a</code></td>
</tr>
</tbody>
</table>
<p>This syntax allows us to specify many different genetic models.</p>
</section>
<section id="common-factor-model" class="level3" data-number="1.0.21">
<h3 data-number="1.0.21" class="anchored" data-anchor-id="common-factor-model"><span class="header-section-number">1.0.21</span> 14. Common Factor Model</h3>
<p>A common factor model assumes that several observed traits share one underlying latent genetic factor.</p>
<p>For example:</p>
<p>$ F1 MDD, PTSD, ALCH, ANX $</p>
<p>Here, <code>F1</code> represents a shared internalizing genetic factor.</p>
<div id="a38be58a-bae0-4d6b-942b-22c71bfd38e6" class="cell" data-execution_count="21">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define covariance structure</span></span>
<span id="cb12-2">covstruc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> LDSC_INT</span>
<span id="cb12-3"></span>
<span id="cb12-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Common factor model</span></span>
<span id="cb12-5">INT.model <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;">"</span></span>
<span id="cb12-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">F1 =~ MDD + PTSD + ALCH + ANX</span></span>
<span id="cb12-7"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb12-8"></span>
<span id="cb12-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Use unit variance identification</span></span>
<span id="cb12-10">std.lv <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="cb12-11"></span>
<span id="cb12-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run model</span></span>
<span id="cb12-13">IntResults <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">usermodel</span>(</span>
<span id="cb12-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">covstruc =</span> covstruc,</span>
<span id="cb12-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> INT.model,</span>
<span id="cb12-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">std.lv =</span> std.lv</span>
<span id="cb12-17">)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Running primary model"
[1] "Calculating Standardized Results"
[1] "Calculating SRMR"
elapsed 
  0.175 </code></pre>
</div>
</div>
</section>
<section id="genetic-multiple-regression" class="level3" data-number="1.0.22">
<h3 data-number="1.0.22" class="anchored" data-anchor-id="genetic-multiple-regression"><span class="header-section-number">1.0.22</span> 15. Genetic Multiple Regression</h3>
<p>Genomic SEM is not limited to factor models. It can also estimate genetic regression models.</p>
<p>For example, suppose we want to know whether the genetic component of educational attainment is associated with schizophrenia and bipolar disorder.</p>
<p>A simplified model could be:</p>
<p>[ EA_g = b_1SCZ_g + b_2BIP_g + u]</p>
<p>This means that the genetic component of educational attainment is regressed on the genetic components of schizophrenia and bipolar disorder.</p>
<p>In lavaan-style syntax, this could be written as:</p>
<p>model &lt;- ” EA ~ SCZ + BIP SCZ <sub></sub> BIP ”</p>
<p>This allows us to ask whether one trait explains unique genetic variation in another trait after accounting for additional genetically correlated traits.</p>
</section>
<section id="gwas-by-subtraction" class="level3" data-number="1.0.23">
<h3 data-number="1.0.23" class="anchored" data-anchor-id="gwas-by-subtraction"><span class="header-section-number">1.0.23</span> 16. GWAS-by-Subtraction</h3>
<p>GWAS-by-subtraction is one of the important applications of Genomic SEM.</p>
<p>The idea is to separate shared and residual genetic components.</p>
<p>For example, educational attainment and cognitive performance are genetically correlated. But educational attainment is influenced by both cognitive and non-cognitive factors.</p>
<p>A Genomic SEM model can estimate:</p>
<p>A cognitive genetic factor shared with cognitive performance A non-cognitive genetic component of educational attainment</p>
<p>Conceptually:</p>
<p>$ EA = Cognitive + NonCognitive $</p>
<p>This allows researchers to perform GWAS on the residual non-cognitive component.</p>
<p>In simple terms, GWAS-by-subtraction asks:</p>
<p>What genetic signal remains in one trait after removing the genetic signal shared with another trait?</p>
<p>This is useful when we want to isolate more specific genetic pathways.</p>
</section>
<section id="view-model-results" class="level3" data-number="1.0.24">
<h3 data-number="1.0.24" class="anchored" data-anchor-id="view-model-results"><span class="header-section-number">1.0.24</span> 15. View Model Results</h3>
<p>The results table contains:</p>
<ul>
<li>Parameter estimates</li>
<li>Standard errors</li>
<li>Standardized estimates</li>
<li>p-values</li>
</ul>
<p>The factor loadings tell us how strongly each trait relates to the latent genetic factor.</p>
<div id="3458d1a1-1eac-4fad-a889-76189976a6f6" class="cell" data-execution_count="23">
<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">IntResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>results</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 9 × 9</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">lhs</th>
<th data-quarto-table-cell-role="th" scope="col">op</th>
<th data-quarto-table-cell-role="th" scope="col">rhs</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_Est</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_All</th>
<th data-quarto-table-cell-role="th" scope="col">p_value</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>F1</td>
<td>=~</td>
<td>MDD</td>
<td>0.283806747</td>
<td>0.021002745436444</td>
<td>0.97326125</td>
<td>0.0720249151052966</td>
<td>0.97326125</td>
<td>1.313540e-41</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>F1</td>
<td>=~</td>
<td>PTSD</td>
<td>0.221278068</td>
<td>0.0402049336545347</td>
<td>0.45226835</td>
<td>0.0821745168725034</td>
<td>0.45226834</td>
<td>3.717880e-08</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>F1</td>
<td>=~</td>
<td>ALCH</td>
<td>0.205225639</td>
<td>0.024321802328951</td>
<td>0.54969157</td>
<td>0.0651453167330757</td>
<td>0.54969157</td>
<td>3.230100e-17</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>F1</td>
<td>=~</td>
<td>ANX</td>
<td>0.445784749</td>
<td>0.032456114148652</td>
<td>0.92294074</td>
<td>0.0671962594562505</td>
<td>0.92294072</td>
<td>6.265550e-43</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>ALCH</td>
<td>~~</td>
<td>ALCH</td>
<td>0.097270350</td>
<td>0.025899146459423</td>
<td>0.69783919</td>
<td>0.185806270387686</td>
<td>0.69783918</td>
<td>1.728330e-04</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">9</th>
<td>PTSD</td>
<td>~~</td>
<td>PTSD</td>
<td>0.190414108</td>
<td>0.106977265864464</td>
<td>0.79545336</td>
<td>0.446896663140437</td>
<td>0.79545335</td>
<td>7.508426e-02</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">8</th>
<td>MDD</td>
<td>~~</td>
<td>MDD</td>
<td>0.004486541</td>
<td>0.0109566843706871</td>
<td>0.05276254</td>
<td>0.12885240976165</td>
<td>0.05276254</td>
<td>6.821876e-01</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>ANX</td>
<td>~~</td>
<td>ANX</td>
<td>0.034569558</td>
<td>0.0301103378331493</td>
<td>0.14818043</td>
<td>0.129066285535458</td>
<td>0.14818043</td>
<td>2.509289e-01</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">7</th>
<td>F1</td>
<td>~~</td>
<td>F1</td>
<td>1.000000000</td>
<td></td>
<td>1.00000000</td>
<td></td>
<td>1.00000000</td>
<td>NA</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="view-model-fit" class="level3" data-number="1.0.25">
<h3 data-number="1.0.25" class="anchored" data-anchor-id="view-model-fit"><span class="header-section-number">1.0.25</span> 16. View Model Fit</h3>
<p>Model fit tells us whether the proposed model explains the observed genetic covariance matrix well.</p>
<p>Important fit statistics include:</p>
<ul>
<li>Chi-square: lower is better</li>
<li>AIC: useful for comparing models</li>
<li>CFI: higher is better</li>
<li>SRMR: lower is better</li>
</ul>
<p>As a rough guide:</p>
<ul>
<li>CFI &gt; 0.90 suggests acceptable fit</li>
<li>CFI &gt; 0.95 suggests good fit</li>
<li>SRMR &lt; 0.10 suggests acceptable fit</li>
<li>SRMR &lt; 0.05 suggests good fit</li>
</ul>
<div id="c7dce095-c099-44c1-b38f-2084d99989b5" class="cell" data-execution_count="25">
<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">IntResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>modelfit</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">df</th>
<th data-quarto-table-cell-role="th" scope="col">p_chisq</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">CFI</th>
<th data-quarto-table-cell-role="th" scope="col">SRMR</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">df</th>
<td>1.283452</td>
<td>2</td>
<td>0.526383</td>
<td>17.28345</td>
<td>1</td>
<td>0.03621695</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="interpreting-the-common-factor-model" class="level3" data-number="1.0.26">
<h3 data-number="1.0.26" class="anchored" data-anchor-id="interpreting-the-common-factor-model"><span class="header-section-number">1.0.26</span> 17. Interpreting the Common Factor Model</h3>
<p>A strong loading of MDD on F1 means that major depression strongly reflects the shared genetic factor.</p>
<p>A weaker loading of ALCH on F1 means that alcohol use disorder may share some genetic risk with the factor, but also has more trait-specific genetic influences.</p>
<p>The residual variance of each trait represents genetic variation not explained by the common factor.</p>
</section>
<section id="alternative-model-correlated-traits-model" class="level3" data-number="1.0.27">
<h3 data-number="1.0.27" class="anchored" data-anchor-id="alternative-model-correlated-traits-model"><span class="header-section-number">1.0.27</span> 18. Alternative Model: Correlated Traits Model</h3>
<p>Instead of forcing all traits to load on a common factor, we could estimate pairwise genetic covariances directly.</p>
<p>This is useful when we do not want to assume a latent factor.</p>
<div id="8e525361-73ca-4fcc-b579-cb1f7ee5365f" class="cell" data-execution_count="27">
<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">correlated.model <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;">"</span></span>
<span id="cb16-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">MDD ~~ PTSD</span></span>
<span id="cb16-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">MDD ~~ ALCH</span></span>
<span id="cb16-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">MDD ~~ ANX</span></span>
<span id="cb16-5"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">PTSD ~~ ALCH</span></span>
<span id="cb16-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">PTSD ~~ ANX</span></span>
<span id="cb16-7"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">ALCH ~~ ANX</span></span>
<span id="cb16-8"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb16-9"></span>
<span id="cb16-10">CorResults <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">usermodel</span>(</span>
<span id="cb16-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">covstruc =</span> LDSC_INT,</span>
<span id="cb16-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> correlated.model,</span>
<span id="cb16-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">std.lv =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb16-14">)</span>
<span id="cb16-15"></span>
<span id="cb16-16">CorResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>results</span>
<span id="cb16-17">CorResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>modelfit</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Running primary model"
[1] "Calculating Standardized Results"
[1] "Calculating SRMR"
elapsed 
  0.104 
[1] "Model fit statistics are all printed as NA as you have specified a fully saturated model (i.e., df = 0)"</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 10 × 9</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">lhs</th>
<th data-quarto-table-cell-role="th" scope="col">op</th>
<th data-quarto-table-cell-role="th" scope="col">rhs</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_Est</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_All</th>
<th data-quarto-table-cell-role="th" scope="col">p_value</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">7</th>
<td>MDD</td>
<td>~~</td>
<td>PTSD</td>
<td>0.05799439</td>
<td>0.011560951</td>
<td>0.4064906</td>
<td>0.08103228</td>
<td>0.4064906</td>
<td>5.264780e-07</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>MDD</td>
<td>~~</td>
<td>ALCH</td>
<td>0.05943021</td>
<td>0.006076568</td>
<td>0.5458853</td>
<td>0.05581520</td>
<td>0.5458853</td>
<td>1.369039e-22</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>MDD</td>
<td>~~</td>
<td>ANX</td>
<td>0.12667327</td>
<td>0.007147882</td>
<td>0.8993739</td>
<td>0.05074961</td>
<td>0.8993739</td>
<td>2.847008e-70</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">8</th>
<td>PTSD</td>
<td>~~</td>
<td>ALCH</td>
<td>0.05977947</td>
<td>0.041025806</td>
<td>0.3272633</td>
<td>0.22459619</td>
<td>0.3272633</td>
<td>1.450836e-01</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">9</th>
<td>PTSD</td>
<td>~~</td>
<td>ANX</td>
<td>0.11428679</td>
<td>0.028723611</td>
<td>0.4836180</td>
<td>0.12154733</td>
<td>0.4836180</td>
<td>6.925092e-05</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>ALCH</td>
<td>~~</td>
<td>ANX</td>
<td>0.08500236</td>
<td>0.016208124</td>
<td>0.4713755</td>
<td>0.08988118</td>
<td>0.4713755</td>
<td>1.567668e-07</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>ALCH</td>
<td>~~</td>
<td>ALCH</td>
<td>0.13938790</td>
<td>0.024579672</td>
<td>1.0000000</td>
<td>0.17634007</td>
<td>1.0000000</td>
<td>1.420817e-08</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">10</th>
<td>PTSD</td>
<td>~~</td>
<td>PTSD</td>
<td>0.23937808</td>
<td>0.106582777</td>
<td>1.0000000</td>
<td>0.44524869</td>
<td>1.0000000</td>
<td>2.470812e-02</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>MDD</td>
<td>~~</td>
<td>MDD</td>
<td>0.08503281</td>
<td>0.003491874</td>
<td>1.0000000</td>
<td>0.04106502</td>
<td>1.0000000</td>
<td>5.572026e-131</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>ANX</td>
<td>~~</td>
<td>ANX</td>
<td>0.23329361</td>
<td>0.016862213</td>
<td>1.0000000</td>
<td>0.07227893</td>
<td>1.0000000</td>
<td>1.561049e-43</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">df</th>
<th data-quarto-table-cell-role="th" scope="col">p_chisq</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">CFI</th>
<th data-quarto-table-cell-role="th" scope="col">SRMR</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">df</th>
<td>NA</td>
<td>0</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="alternative-model-regression-model" class="level3" data-number="1.0.28">
<h3 data-number="1.0.28" class="anchored" data-anchor-id="alternative-model-regression-model"><span class="header-section-number">1.0.28</span> 19. Alternative Model: Regression Model</h3>
<p>Genomic SEM can also fit genetic regression models.</p>
<p>For example, we can ask whether the genetic component of anxiety predicts the genetic component of depression.</p>
<div id="f41487b9-8553-44ac-9278-04e4801e9495" class="cell" data-execution_count="28">
<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">regression.model <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;">"</span></span>
<span id="cb18-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">MDD ~ ANX + PTSD + ALCH</span></span>
<span id="cb18-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">ANX ~~ PTSD</span></span>
<span id="cb18-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">ANX ~~ ALCH</span></span>
<span id="cb18-5"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">PTSD ~~ ALCH</span></span>
<span id="cb18-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb18-7"></span>
<span id="cb18-8">RegResults <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">usermodel</span>(</span>
<span id="cb18-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">covstruc =</span> LDSC_INT,</span>
<span id="cb18-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> regression.model,</span>
<span id="cb18-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">std.lv =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb18-12">)</span>
<span id="cb18-13"></span>
<span id="cb18-14">RegResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>results</span>
<span id="cb18-15">RegResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>modelfit</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Running primary model"
[1] "Calculating Standardized Results"
[1] "Calculating SRMR"
elapsed 
  0.115 
[1] "Model fit statistics are all printed as NA as you have specified a fully saturated model (i.e., df = 0)"</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 10 × 9</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">lhs</th>
<th data-quarto-table-cell-role="th" scope="col">op</th>
<th data-quarto-table-cell-role="th" scope="col">rhs</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_Est</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_All</th>
<th data-quarto-table-cell-role="th" scope="col">p_value</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">7</th>
<td>MDD</td>
<td>~</td>
<td>ANX</td>
<td>0.51330125</td>
<td>0.068314744</td>
<td>0.85021835</td>
<td>0.11315470</td>
<td>0.85021835</td>
<td>5.744864e-14</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">8</th>
<td>MDD</td>
<td>~</td>
<td>PTSD</td>
<td>-0.03483028</td>
<td>0.094099604</td>
<td>-0.05843942</td>
<td>0.15788349</td>
<td>-0.05843942</td>
<td>7.112762e-01</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>MDD</td>
<td>~</td>
<td>ALCH</td>
<td>0.12827888</td>
<td>0.075097732</td>
<td>0.16423830</td>
<td>0.09614929</td>
<td>0.16423830</td>
<td>8.760680e-02</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>ANX</td>
<td>~~</td>
<td>PTSD</td>
<td>0.11428679</td>
<td>0.028723611</td>
<td>0.48361796</td>
<td>0.12154733</td>
<td>0.48361796</td>
<td>6.925093e-05</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>ANX</td>
<td>~~</td>
<td>ALCH</td>
<td>0.08500236</td>
<td>0.016208124</td>
<td>0.47137552</td>
<td>0.08988118</td>
<td>0.47137551</td>
<td>1.567668e-07</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">9</th>
<td>PTSD</td>
<td>~~</td>
<td>ALCH</td>
<td>0.05977947</td>
<td>0.041025806</td>
<td>0.32726331</td>
<td>0.22459619</td>
<td>0.32726331</td>
<td>1.450836e-01</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>ALCH</td>
<td>~~</td>
<td>ALCH</td>
<td>0.13938790</td>
<td>0.024579672</td>
<td>1.00000001</td>
<td>0.17634007</td>
<td>1.00000001</td>
<td>1.420816e-08</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">10</th>
<td>PTSD</td>
<td>~~</td>
<td>PTSD</td>
<td>0.23937808</td>
<td>0.106582777</td>
<td>0.99999999</td>
<td>0.44524869</td>
<td>0.99999999</td>
<td>2.470812e-02</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>MDD</td>
<td>~~</td>
<td>MDD</td>
<td>0.01440758</td>
<td>0.005525258</td>
<td>0.16943560</td>
<td>0.06497795</td>
<td>0.16943560</td>
<td>9.118313e-03</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>ANX</td>
<td>~~</td>
<td>ANX</td>
<td>0.23329361</td>
<td>0.016862213</td>
<td>1.00000000</td>
<td>0.07227893</td>
<td>1.00000000</td>
<td>1.561050e-43</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">df</th>
<th data-quarto-table-cell-role="th" scope="col">p_chisq</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">CFI</th>
<th data-quarto-table-cell-role="th" scope="col">SRMR</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">df</th>
<td>NA</td>
<td>0</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="multivariate-gwas-in-genomic-sem" class="level3" data-number="1.0.29">
<h3 data-number="1.0.29" class="anchored" data-anchor-id="multivariate-gwas-in-genomic-sem"><span class="header-section-number">1.0.29</span> 20. Multivariate GWAS in Genomic SEM</h3>
<p>So far, we estimated a genome-wide model using the genetic covariance matrix.</p>
<p>Now we move to multivariate GWAS.</p>
<p>The goal is to test SNP effects on a latent factor.</p>
<p>Instead of asking:</p>
<blockquote class="blockquote">
<p>Is this SNP associated with MDD?</p>
</blockquote>
<p>we ask:</p>
<blockquote class="blockquote">
<p>Is this SNP associated with the shared genetic factor underlying MDD, PTSD, ALCH, and ANX?</p>
</blockquote>
<p>This can increase power and improve interpretation when traits share genetic architecture.</p>
</section>
<section id="steps-for-multivariate-gwas" class="level3" data-number="1.0.30">
<h3 data-number="1.0.30" class="anchored" data-anchor-id="steps-for-multivariate-gwas"><span class="header-section-number">1.0.30</span> 21. Steps for Multivariate GWAS</h3>
<p>Multivariate GWAS in Genomic SEM has four main steps:</p>
<ol type="1">
<li>Munge summary statistics</li>
<li>Run LD Score Regression</li>
<li>Prepare summary statistics using <code>sumstats</code></li>
<li>Run multivariate GWAS using <code>userGWAS</code></li>
</ol>
<p>The first two steps are the same as before. If we already ran LDSC for the same traits, we do not need to repeat it.</p>
</section>
<section id="step-3-for-multivariate-gwas-prepare-snp-summary-statistics" class="level3" data-number="1.0.31">
<h3 data-number="1.0.31" class="anchored" data-anchor-id="step-3-for-multivariate-gwas-prepare-snp-summary-statistics"><span class="header-section-number">1.0.31</span> 22. Step 3 for Multivariate GWAS: Prepare SNP Summary Statistics</h3>
<p>The <code>sumstats()</code> function prepares SNP-level summary statistics for <code>userGWAS</code>.</p>
<p>In the workshop practical, reduced chromosome 4 files are used for demonstration.</p>
<div id="678a59f0-a161-4c81-863a-7155bd18aed5" class="cell" data-execution_count="30">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Files must be in the same order as the LDSC traits</span></span>
<span id="cb20-2">files <span class="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;">"ALCH4.txt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PTSD4.txt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MDD4.txt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ANX4.txt"</span>)</span>
<span id="cb20-3"></span>
<span id="cb20-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Reference file for allele frequency</span></span>
<span id="cb20-5">ref <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;">"reference.1000G.ch4.txt"</span></span>
<span id="cb20-6"></span>
<span id="cb20-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Trait names</span></span>
<span id="cb20-8">trait.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;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ALCH"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PTSD"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MDD"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ANX"</span>)</span>
<span id="cb20-9"></span>
<span id="cb20-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Whether SEs are on logistic scale</span></span>
<span id="cb20-11">se.logit <span class="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="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb20-12"></span>
<span id="cb20-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Whether linear probability model correction is needed</span></span>
<span id="cb20-14">linprob <span class="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="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb20-15"></span>
<span id="cb20-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample size argument</span></span>
<span id="cb20-17">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;">c</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>)</span>
<span id="cb20-18"></span>
<span id="cb20-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Prepare summary statistics</span></span>
<span id="cb20-20">INT_sumstats <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sumstats</span>(</span>
<span id="cb20-21">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">files =</span> files,</span>
<span id="cb20-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ref =</span> ref,</span>
<span id="cb20-23">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trait.names =</span> trait.names,</span>
<span id="cb20-24">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se.logit =</span> se.logit,</span>
<span id="cb20-25">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linprob =</span> linprob,</span>
<span id="cb20-26">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">N =</span> N</span>
<span id="cb20-27">)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>The preparation of 4 summary statistics for use in Genomic SEM began at: 2026-06-10 12:44:42.44117
Please note that the files should be in the same order that they were listed for the ldsc function
Reading in reference file
Applying MAF filer of 0.01 to the reference file.</code></pre>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>All files loaded into R!
Preparing summary statistics for file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ALCH4.txt
Interpreting the SNP column as the SNP column.
Interpreting the A1 column as the A1 column.
Interpreting the A2 column as the A2 column.
Interpreting the Z column as the effect column.
Interpreting the P column as the P column.
Interpreting the WEIGHT column as the N column.
0 rows were removed from the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ALCH4.txt summary statistics file due to entries that were duplicated for rsID. These are removed as they likely reflect multiallelic variants.
Merging file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ALCH4.txt with the reference file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/reference.1000G.ch4.txt
1000 rows present in the full /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ALCH4.txt summary statistics file.
0 rows were removed from the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ALCH4.txt summary statistics file as the rsIDs for these SNPs were not present in the reference file.
The effect column was determined NOT to be coded as an odds ratio (OR) for the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ALCH4.txt summary statistics file based on the median of the effect column being close to 0.
An transformation used to back out logistic betas for binary traits is being applied for: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ALCH4.txt
No INFO column, cannot filter on INFO, which may influence results
1000 SNPs are left in the summary statistics file /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ALCH4.txt after QC and merging with the reference file.
Preparing summary statistics for file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt
Interpreting the MARKERNAME column as the SNP column.
Interpreting the ALLELE1 column as the A1 column.
Interpreting the ALLELE2 column as the A2 column.
Interpreting the EFFECT column as the effect column.
Interpreting the P.VALUE column as the P column.
Cannot find N column, try renaming it to N in the summary statistics file for:/Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt
Interpreting the STDERR column as the SE column.
Interpreting the DIRECTION column as the DIRECTION column.
0 rows were removed from the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt summary statistics file due to entries that were duplicated for rsID. These are removed as they likely reflect multiallelic variants.
Merging file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt with the reference file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/reference.1000G.ch4.txt
1000 rows present in the full /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt summary statistics file.
0 rows were removed from the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt summary statistics file as the rsIDs for these SNPs were not present in the reference file.
The effect column was determined NOT to be coded as an odds ratio (OR) for the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt summary statistics file based on the median of the effect column being close to 0.
No INFO column, cannot filter on INFO, which may influence results
Performing transformation under the assumption that the effect column is either an odds ratio or logistic beta (please see output above to determine whether it was interpreted as an odds ratio) and the SE column is a logistic SE (i.e., NOT the SE of the odds ratio) for:/Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt
1000 SNPs are left in the summary statistics file /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/PTSD4.txt after QC and merging with the reference file.
Preparing summary statistics for file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txt
Found an NEFF column for sample size. 

Please note that this is likely effective sample size and should only be used for liability h^2 conversion for binary traits and that it should reflect the sum of effective sample sizes across cohorts.

Be aware that some NEFF columns reflect half of the effective sample size; the function will automatically double the column names if recognized [check above in .log file to determine if this is the case].
If the Neff value is halved in the summary stats, but not recognized by the munge function, this should be manually doubled prior to running munge.
Interpreting the MARKERNAME column as the SNP column.
Interpreting the A1 column as the A1 column.
Interpreting the A2 column as the A2 column.
Interpreting the LOGOR column as the effect column.
Interpreting the P column as the P column.
Interpreting the NEFF column as the N column.
Interpreting the MAF column as the MAF column.
Interpreting the STDERRLOGOR column as the SE column.
0 rows were removed from the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txt summary statistics file due to entries that were duplicated for rsID. These are removed as they likely reflect multiallelic variants.
Merging file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txt with the reference file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/reference.1000G.ch4.txt
1400 rows present in the full /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txt summary statistics file.
20 rows were removed from the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txt summary statistics file as the rsIDs for these SNPs were not present in the reference file.
The effect column was determined NOT to be coded as an odds ratio (OR) for the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txt summary statistics file based on the median of the effect column being close to 0.
5rows were removed from the/Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txtsummary statistics file due to effect values estimated at exactly 0 as this causes problems for matrix inversion necessary for later Genomic SEM analyses.
No INFO column, cannot filter on INFO, which may influence results
Performing transformation under the assumption that the effect column is either an odds ratio or logistic beta (please see output above to determine whether it was interpreted as an odds ratio) and the SE column is a logistic SE (i.e., NOT the SE of the odds ratio) for:/Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txt
1375 SNPs are left in the summary statistics file /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/MDD4.txt after QC and merging with the reference file.
Preparing summary statistics for file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ANX4.txt
Found an NEFF column for sample size. 

Please note that this is likely effective sample size and should only be used for liability h^2 conversion for binary traits and that it should reflect the sum of effective sample sizes across cohorts.

Be aware that some NEFF columns reflect half of the effective sample size; the function will automatically double the column names if recognized [check above in .log file to determine if this is the case].
If the Neff value is halved in the summary stats, but not recognized by the munge function, this should be manually doubled prior to running munge.
Interpreting the SNP column as the SNP column.
Interpreting the ALLELE1 column as the A1 column.
Interpreting the ALLELE2 column as the A2 column.
Interpreting the EFFECT column as the effect column.
Interpreting the P column as the P column.
Interpreting the NEFF column as the N column.
Interpreting the STDERR column as the SE column.
Interpreting the DIRECTION column as the DIRECTION column.
0 rows were removed from the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ANX4.txt summary statistics file due to entries that were duplicated for rsID. These are removed as they likely reflect multiallelic variants.
Merging file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ANX4.txt with the reference file: /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/reference.1000G.ch4.txt
1000 rows present in the full /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ANX4.txt summary statistics file.
0 rows were removed from the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ANX4.txt summary statistics file as the rsIDs for these SNPs were not present in the reference file.
The effect column was determined NOT to be coded as an odds ratio (OR) for the /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ANX4.txt summary statistics file based on the median of the effect column being close to 0.
No INFO column, cannot filter on INFO, which may influence results
Performing transformation under the assumption that the effect column is either an odds ratio or logistic beta (please see output above to determine whether it was interpreted as an odds ratio) and the SE column is a logistic SE (i.e., NOT the SE of the odds ratio) for:/Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ANX4.txt
1000 SNPs are left in the summary statistics file /Users/nbhadra/Documents/aSchork/ISG_2026/Scripts/script_day6/GenomicSEM_2026/ANX4.txt after QC and merging with the reference file.
After merging across all summary statistics using listwise deletion, performing QC, and merging with the reference file, there are 1000 SNPs left in the final multivariate summary statistics file
Sumstats finished running at 2026-06-10 12:44:44.381982
Running sumstats for all files took 0 minutes and 1.94081211090088 seconds
Please check the log file ALCH_PTSD_MDD_ANX_sumstats.log to ensure that all columns were interpreted correctly and no warnings were issued for any of the summary statistics files.</code></pre>
</div>
</div>
</section>
<section id="why-linprob-is-needed" class="level3" data-number="1.0.32">
<h3 data-number="1.0.32" class="anchored" data-anchor-id="why-linprob-is-needed"><span class="header-section-number">1.0.32</span> 23. Why <code>linprob</code> Is Needed</h3>
<p>Sometimes binary traits are analyzed as continuous outcomes, or the summary statistics contain only Z-statistics.</p>
<p>In these cases, Genomic SEM needs additional information to reconstruct the appropriate beta and standard error.</p>
<p>In this practical, <code>linprob = TRUE</code> is used for ALCH.</p>
</section>
<section id="step-4-run-usergwas" class="level3" data-number="1.0.33">
<h3 data-number="1.0.33" class="anchored" data-anchor-id="step-4-run-usergwas"><span class="header-section-number">1.0.33</span> 24. Step 4: Run userGWAS</h3>
<p>Now we run a multivariate GWAS.</p>
<p>The model is:</p>
<p>$ F1 =~ MDD + PTSD + ALCH + ANX $</p>
<p>and then:</p>
<p>$ F1 SNP $</p>
<p>This tests whether each SNP predicts the shared latent genetic factor.</p>
<div id="e65dbd05-2af7-4fa8-bb29-e10af474a0b5" class="cell" data-execution_count="32">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Covariance structure from LDSC</span></span>
<span id="cb23-2">covstruc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> LDSC_INT</span>
<span id="cb23-3"></span>
<span id="cb23-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># SNP-level summary statistics</span></span>
<span id="cb23-5">SNPs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> INT_sumstats</span>
<span id="cb23-6"></span>
<span id="cb23-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Multivariate GWAS model</span></span>
<span id="cb23-8">model <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;">"</span></span>
<span id="cb23-9"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">F1 =~ MDD + PTSD + ALCH + ANX</span></span>
<span id="cb23-10"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">F1 ~ SNP</span></span>
<span id="cb23-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb23-12"></span>
<span id="cb23-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save only the SNP effect on F1</span></span>
<span id="cb23-14">sub <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;">"F1~SNP"</span></span>
<span id="cb23-15"></span>
<span id="cb23-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Practical uses serial processing</span></span>
<span id="cb23-17">parallel <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;">FALSE</span></span>
<span id="cb23-18"></span>
<span id="cb23-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Calculate QSNP</span></span>
<span id="cb23-20">Q_SNP <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="cb23-21"></span>
<span id="cb23-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run multivariate GWAS</span></span>
<span id="cb23-23">INT_GWAS <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">userGWAS</span>(</span>
<span id="cb23-24">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">covstruc =</span> covstruc,</span>
<span id="cb23-25">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">SNPs =</span> SNPs,</span>
<span id="cb23-26">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> model,</span>
<span id="cb23-27">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sub =</span> sub,</span>
<span id="cb23-28">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">parallel =</span> parallel,</span>
<span id="cb23-29">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Q_SNP =</span> Q_SNP</span>
<span id="cb23-30">)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Please note that an update was made to userGWAS on Sept 1 2023  so that the default behavior is to fix the measurement model using the fix_measurement argument."
[1] "Starting GWAS Estimation"
Running Model: 1
Running Model: 1000
elapsed 
 26.264 </code></pre>
</div>
</div>
</section>
<section id="view-the-first-rows-of-the-multivariate-gwas-output" class="level3" data-number="1.0.34">
<h3 data-number="1.0.34" class="anchored" data-anchor-id="view-the-first-rows-of-the-multivariate-gwas-output"><span class="header-section-number">1.0.34</span> 25. View the First Rows of the Multivariate GWAS Output</h3>
<p>The output contains:</p>
<ul>
<li>SNP effect on the factor</li>
<li>Standard error</li>
<li>p-value</li>
<li>QSNP statistic</li>
<li>QSNP p-value</li>
<li>Warnings and errors</li>
</ul>
<div id="9aff38aa-fe7e-43a3-9cb4-1e97f562f147" class="cell" data-execution_count="33">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb25-1">INT_GWAS[[<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><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, ]</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 5 × 24</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">SNP</th>
<th data-quarto-table-cell-role="th" scope="col">CHR</th>
<th data-quarto-table-cell-role="th" scope="col">BP</th>
<th data-quarto-table-cell-role="th" scope="col">MAF</th>
<th data-quarto-table-cell-role="th" scope="col">A1</th>
<th data-quarto-table-cell-role="th" scope="col">A2</th>
<th data-quarto-table-cell-role="th" scope="col">lhs</th>
<th data-quarto-table-cell-role="th" scope="col">op</th>
<th data-quarto-table-cell-role="th" scope="col">rhs</th>
<th data-quarto-table-cell-role="th" scope="col">free</th>
<th data-quarto-table-cell-role="th" scope="col">⋯</th>
<th data-quarto-table-cell-role="th" scope="col">Pval_Estimate</th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">chisq_df</th>
<th data-quarto-table-cell-role="th" scope="col">chisq_pval</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">Q_SNP</th>
<th data-quarto-table-cell-role="th" scope="col">Q_SNP_df</th>
<th data-quarto-table-cell-role="th" scope="col">Q_SNP_pval</th>
<th data-quarto-table-cell-role="th" scope="col">error</th>
<th data-quarto-table-cell-role="th" scope="col">warning</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">⋯</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>rs10030871</td>
<td>4</td>
<td>68786</td>
<td>0.0765408</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8257532</td>
<td>4.905573</td>
<td>8</td>
<td>0.7676193</td>
<td>18.90557</td>
<td>3.622121</td>
<td>3</td>
<td>0.3052654</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>rs6599368</td>
<td>4</td>
<td>69567</td>
<td>0.0755467</td>
<td>A</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8059251</td>
<td>4.839517</td>
<td>8</td>
<td>0.7745831</td>
<td>18.83952</td>
<td>3.556062</td>
<td>3</td>
<td>0.3135635</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>rs7678633</td>
<td>4</td>
<td>69713</td>
<td>0.0755467</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.7979215</td>
<td>4.901617</td>
<td>8</td>
<td>0.7680379</td>
<td>18.90162</td>
<td>3.618164</td>
<td>3</td>
<td>0.3057569</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>rs13130581</td>
<td>4</td>
<td>70392</td>
<td>0.0725646</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9840311</td>
<td>5.029483</td>
<td>8</td>
<td>0.7544203</td>
<td>19.02948</td>
<td>3.746031</td>
<td>3</td>
<td>0.2902263</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>rs13125929</td>
<td>4</td>
<td>71566</td>
<td>0.0725646</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9069168</td>
<td>5.787662</td>
<td>8</td>
<td>0.6710031</td>
<td>19.78766</td>
<td>4.504209</td>
<td>3</td>
<td>0.2119151</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="check-warnings-and-errors" class="level3" data-number="1.0.35">
<h3 data-number="1.0.35" class="anchored" data-anchor-id="check-warnings-and-errors"><span class="header-section-number">1.0.35</span> 26. Check Warnings and Errors</h3>
<p>Before interpreting results, always check warnings and errors.</p>
<p>A value of 0 usually means the SNP was estimated successfully.</p>
<div id="b1e9687e-5870-420c-8012-7cc24e0c4175" class="cell" data-execution_count="34">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Warnings</span></span>
<span id="cb26-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(INT_GWAS[[<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>warning)</span>
<span id="cb26-3"></span>
<span id="cb26-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Errors</span></span>
<span id="cb26-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(INT_GWAS[[<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>error)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>
lavaan-&gt;lav_lavaan_step02_options():  \n   the following argument(s) override(s) the options in slotOptions: se 
                                                                                                           1000 </code></pre>
</div>
<div class="cell-output cell-output-display">
<pre><code>
   0 
1000 </code></pre>
</div>
</div>
</section>
<section id="genome-wide-significant-factor-hits" class="level3" data-number="1.0.36">
<h3 data-number="1.0.36" class="anchored" data-anchor-id="genome-wide-significant-factor-hits"><span class="header-section-number">1.0.36</span> 27. Genome-Wide Significant Factor Hits</h3>
<p>The standard genome-wide significance threshold is:</p>
<p>$ 5 ^{-8} $</p>
<p>We can check how many SNPs are significantly associated with the latent factor.</p>
<div id="abba0050-0f43-4ad2-9ae7-0456c362614e" class="cell" data-execution_count="36">
<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;">table</span>(INT_GWAS[[<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>Pval_Estimate <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;">5e-8</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>
FALSE 
 1000 </code></pre>
</div>
</div>
</section>
<section id="qsnp-testing-snp-level-heterogeneity" class="level3" data-number="1.0.37">
<h3 data-number="1.0.37" class="anchored" data-anchor-id="qsnp-testing-snp-level-heterogeneity"><span class="header-section-number">1.0.37</span> 28. QSNP: Testing SNP-Level Heterogeneity</h3>
<p>QSNP tests whether the SNP effect fits the common pathway model.</p>
<p>If a SNP acts mainly through the common factor, then its effects on individual traits should be consistent with the factor structure.</p>
<p>If the SNP has a strong trait-specific effect, the common pathway model may not fit well.</p>
<p>A significant QSNP value suggests SNP-level heterogeneity.</p>
<p>This means the SNP may affect one or more traits differently than expected from the common factor model.</p>
<p>QSNP can be used in two ways:</p>
<p>As a quality-control metric As a biological result</p>
<p>As a QC metric, it can help identify SNPs that do not cleanly represent the common factor.</p>
<p>As a biological result, it can highlight SNPs that differentiate related traits.</p>
</section>
<section id="qsnp-as-a-qc-metric" class="level3" data-number="1.0.38">
<h3 data-number="1.0.38" class="anchored" data-anchor-id="qsnp-as-a-qc-metric"><span class="header-section-number">1.0.38</span> 29. QSNP as a QC Metric</h3>
<p>Suppose a SNP is significantly associated with an internalizing factor.</p>
<p>If QSNP is not significant, this suggests that the SNP effect is consistent with the shared factor.</p>
<p>But if QSNP is highly significant, the SNP may not be a clean factor SNP.</p>
<p>It may be driven mainly by one phenotype.</p>
<p>For example, a SNP may look associated with an internalizing factor, but the effect may actually be much stronger for depression than anxiety or PTSD.</p>
<p>In that case, QSNP warns us that the SNP may have trait-specific effects.</p>
</section>
<section id="qsnp-as-a-biological-result" class="level3" data-number="1.0.39">
<h3 data-number="1.0.39" class="anchored" data-anchor-id="qsnp-as-a-biological-result"><span class="header-section-number">1.0.39</span> 30. QSNP as a Biological Result</h3>
<p>QSNP is not only a warning. It can also be scientifically interesting.</p>
<p>A significant QSNP result may reveal SNPs that distinguish traits that are otherwise genetically correlated.</p>
<p>For example, depression and anxiety may share a broad genetic factor, but some variants may be more specific to depression.</p>
<p>Similarly, schizophrenia and bipolar disorder may share genetic liability, but some variants may help differentiate them.</p>
<p>Therefore, QSNP can be used to study genetic specificity within broader shared genetic architecture.</p>
</section>
<section id="multiple-factor-models-and-qsnp" class="level3" data-number="1.0.40">
<h3 data-number="1.0.40" class="anchored" data-anchor-id="multiple-factor-models-and-qsnp"><span class="header-section-number">1.0.40</span> 31. Multiple-Factor Models and QSNP</h3>
<p>In models with multiple factors, QSNP can be calculated for each SNP-factor relationship.</p>
<p>This is useful because a SNP may fit one factor well but show heterogeneity for another factor.</p>
<p>For example, a SNP may operate cleanly through a substance-use factor but show disorder-specific effects within an internalizing factor.</p>
<p>This makes QSNP especially useful in complex psychiatric models where several correlated factors are estimated together.</p>
<div id="f98501bd-a727-4888-a1a6-2281fbe84ce0" class="cell" data-execution_count="37">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Genome-wide significant QSNP hits</span></span>
<span id="cb31-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(INT_GWAS[[<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>Q_SNP_pval <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;">5e-8</span>)</span>
<span id="cb31-3"></span>
<span id="cb31-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Suggestive QSNP hits</span></span>
<span id="cb31-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(INT_GWAS[[<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>Q_SNP_pval <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-5</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>
FALSE 
 1000 </code></pre>
</div>
<div class="cell-output cell-output-display">
<pre><code>
FALSE  TRUE 
  926    74 </code></pre>
</div>
</div>
</section>
<section id="interpreting-qsnp" class="level3" data-number="1.0.41">
<h3 data-number="1.0.41" class="anchored" data-anchor-id="interpreting-qsnp"><span class="header-section-number">1.0.41</span> 29. Interpreting QSNP</h3>
<p>QSNP can be interpreted in two ways.</p>
<p>First, it can be used as a quality-control metric. If a SNP has a strong factor association but also a very significant QSNP value, the SNP may not represent the common factor cleanly.</p>
<p>Second, QSNP can be a result of interest. It may identify SNPs that differentiate traits from one another.</p>
<p>For example, a SNP may be associated with depression but not anxiety, even though both traits load on the same internalizing factor.</p>
<div id="e2c57d6c-4bc7-49c7-b5fb-bf4792fb45a8" class="cell" data-execution_count="38">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb34-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">View</span>(INT_GWAS[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1000 × 24</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">SNP</th>
<th data-quarto-table-cell-role="th" scope="col">CHR</th>
<th data-quarto-table-cell-role="th" scope="col">BP</th>
<th data-quarto-table-cell-role="th" scope="col">MAF</th>
<th data-quarto-table-cell-role="th" scope="col">A1</th>
<th data-quarto-table-cell-role="th" scope="col">A2</th>
<th data-quarto-table-cell-role="th" scope="col">lhs</th>
<th data-quarto-table-cell-role="th" scope="col">op</th>
<th data-quarto-table-cell-role="th" scope="col">rhs</th>
<th data-quarto-table-cell-role="th" scope="col">free</th>
<th data-quarto-table-cell-role="th" scope="col">⋯</th>
<th data-quarto-table-cell-role="th" scope="col">Pval_Estimate</th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">chisq_df</th>
<th data-quarto-table-cell-role="th" scope="col">chisq_pval</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">Q_SNP</th>
<th data-quarto-table-cell-role="th" scope="col">Q_SNP_df</th>
<th data-quarto-table-cell-role="th" scope="col">Q_SNP_pval</th>
<th data-quarto-table-cell-role="th" scope="col">error</th>
<th data-quarto-table-cell-role="th" scope="col">warning</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">⋯</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>rs10030871</td>
<td>4</td>
<td>68786</td>
<td>0.0765408</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8257532</td>
<td>4.905573</td>
<td>8</td>
<td>0.7676193</td>
<td>18.90557</td>
<td>3.622121</td>
<td>3</td>
<td>0.30526541</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs6599368</td>
<td>4</td>
<td>69567</td>
<td>0.0755467</td>
<td>A</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8059251</td>
<td>4.839517</td>
<td>8</td>
<td>0.7745831</td>
<td>18.83952</td>
<td>3.556062</td>
<td>3</td>
<td>0.31356354</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs7678633</td>
<td>4</td>
<td>69713</td>
<td>0.0755467</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.7979215</td>
<td>4.901617</td>
<td>8</td>
<td>0.7680379</td>
<td>18.90162</td>
<td>3.618164</td>
<td>3</td>
<td>0.30575689</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs13130581</td>
<td>4</td>
<td>70392</td>
<td>0.0725646</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9840311</td>
<td>5.029483</td>
<td>8</td>
<td>0.7544203</td>
<td>19.02948</td>
<td>3.746031</td>
<td>3</td>
<td>0.29022634</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs13125929</td>
<td>4</td>
<td>71566</td>
<td>0.0725646</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9069168</td>
<td>5.787662</td>
<td>8</td>
<td>0.6710031</td>
<td>19.78766</td>
<td>4.504209</td>
<td>3</td>
<td>0.21191512</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs6839041</td>
<td>4</td>
<td>72048</td>
<td>0.2693840</td>
<td>T</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9978168</td>
<td>3.541053</td>
<td>8</td>
<td>0.8959803</td>
<td>17.54105</td>
<td>2.257601</td>
<td>3</td>
<td>0.52069205</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs6851329</td>
<td>4</td>
<td>72303</td>
<td>0.0725646</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9886240</td>
<td>4.880091</td>
<td>8</td>
<td>0.7703120</td>
<td>18.88009</td>
<td>3.596639</td>
<td>3</td>
<td>0.30844301</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs10027065</td>
<td>4</td>
<td>72939</td>
<td>0.0755467</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.7715593</td>
<td>4.943569</td>
<td>8</td>
<td>0.7635902</td>
<td>18.94357</td>
<td>3.660117</td>
<td>3</td>
<td>0.30058151</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs4690284</td>
<td>4</td>
<td>73508</td>
<td>0.1451290</td>
<td>C</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.1241614</td>
<td>2.966177</td>
<td>8</td>
<td>0.9364621</td>
<td>16.96618</td>
<td>1.682725</td>
<td>3</td>
<td>0.64078118</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs13119939</td>
<td>4</td>
<td>73981</td>
<td>0.0725646</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9614800</td>
<td>5.132825</td>
<td>8</td>
<td>0.7432898</td>
<td>19.13283</td>
<td>3.849373</td>
<td>3</td>
<td>0.27819520</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs6599371</td>
<td>4</td>
<td>74015</td>
<td>0.0755467</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8128254</td>
<td>4.837074</td>
<td>8</td>
<td>0.7748395</td>
<td>18.83707</td>
<td>3.553622</td>
<td>3</td>
<td>0.31387385</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs13125667</td>
<td>4</td>
<td>74238</td>
<td>0.0725646</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9843619</td>
<td>5.225879</td>
<td>8</td>
<td>0.7331836</td>
<td>19.22588</td>
<td>3.942427</td>
<td>3</td>
<td>0.26774849</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs10001263</td>
<td>4</td>
<td>74508</td>
<td>0.0755467</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.7706384</td>
<td>5.281466</td>
<td>8</td>
<td>0.7271125</td>
<td>19.28147</td>
<td>3.998014</td>
<td>3</td>
<td>0.26167870</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs11722512</td>
<td>4</td>
<td>74639</td>
<td>0.1819090</td>
<td>A</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9216326</td>
<td>7.046880</td>
<td>8</td>
<td>0.5315833</td>
<td>21.04688</td>
<td>5.763430</td>
<td>3</td>
<td>0.12370462</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs13109067</td>
<td>4</td>
<td>74815</td>
<td>0.0755467</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8393225</td>
<td>4.908892</td>
<td>8</td>
<td>0.7672680</td>
<td>18.90889</td>
<td>3.625440</td>
<td>3</td>
<td>0.30485367</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs13148549</td>
<td>4</td>
<td>74983</td>
<td>0.0755467</td>
<td>T</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.7773565</td>
<td>5.186565</td>
<td>8</td>
<td>0.7374625</td>
<td>19.18656</td>
<td>3.903112</td>
<td>3</td>
<td>0.27211808</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs13114862</td>
<td>4</td>
<td>75102</td>
<td>0.0765408</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8046513</td>
<td>4.687451</td>
<td>8</td>
<td>0.7903995</td>
<td>18.68745</td>
<td>3.403999</td>
<td>3</td>
<td>0.33342816</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs60994255</td>
<td>4</td>
<td>77446</td>
<td>0.1580520</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9382913</td>
<td>6.899311</td>
<td>8</td>
<td>0.5475343</td>
<td>20.89931</td>
<td>5.615860</td>
<td>3</td>
<td>0.13187081</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs59464888</td>
<td>4</td>
<td>77449</td>
<td>0.1640160</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8781014</td>
<td>5.984696</td>
<td>8</td>
<td>0.6489462</td>
<td>19.98470</td>
<td>4.701244</td>
<td>3</td>
<td>0.19502698</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs13435282</td>
<td>4</td>
<td>79340</td>
<td>0.1928430</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.6215750</td>
<td>7.730510</td>
<td>8</td>
<td>0.4602277</td>
<td>21.73051</td>
<td>6.447058</td>
<td>3</td>
<td>0.09177397</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs13434621</td>
<td>4</td>
<td>79535</td>
<td>0.1938370</td>
<td>C</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.5791460</td>
<td>6.954466</td>
<td>8</td>
<td>0.5415533</td>
<td>20.95447</td>
<td>5.671014</td>
<td>3</td>
<td>0.12876046</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs13145153</td>
<td>4</td>
<td>79719</td>
<td>0.0765408</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.6384795</td>
<td>4.872118</td>
<td>8</td>
<td>0.7711529</td>
<td>18.87212</td>
<td>3.588666</td>
<td>3</td>
<td>0.30944321</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs59603164</td>
<td>4</td>
<td>80001</td>
<td>0.1749500</td>
<td>C</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8474933</td>
<td>8.281415</td>
<td>8</td>
<td>0.4064747</td>
<td>22.28142</td>
<td>6.997963</td>
<td>3</td>
<td>0.07196273</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs7664056</td>
<td>4</td>
<td>80132</td>
<td>0.0765408</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.6660829</td>
<td>4.539084</td>
<td>8</td>
<td>0.8055102</td>
<td>18.53908</td>
<td>3.255634</td>
<td>3</td>
<td>0.35386546</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs28716751</td>
<td>4</td>
<td>81303</td>
<td>0.0815109</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.3150613</td>
<td>2.516640</td>
<td>8</td>
<td>0.9609505</td>
<td>16.51664</td>
<td>1.233188</td>
<td>3</td>
<td>0.74505586</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs2187874</td>
<td>4</td>
<td>82321</td>
<td>0.1640160</td>
<td>G</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.7757893</td>
<td>6.046779</td>
<td>8</td>
<td>0.6419918</td>
<td>20.04678</td>
<td>4.763327</td>
<td>3</td>
<td>0.18997076</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs60400620</td>
<td>4</td>
<td>84610</td>
<td>0.1918490</td>
<td>A</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.6593662</td>
<td>7.660052</td>
<td>8</td>
<td>0.4673615</td>
<td>21.66005</td>
<td>6.376598</td>
<td>3</td>
<td>0.09465829</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs61447907</td>
<td>4</td>
<td>84792</td>
<td>0.1918490</td>
<td>C</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.6546304</td>
<td>7.596372</td>
<td>8</td>
<td>0.4738560</td>
<td>21.59637</td>
<td>6.312919</td>
<td>3</td>
<td>0.09733980</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs7667153</td>
<td>4</td>
<td>85422</td>
<td>0.1918490</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.6540012</td>
<td>7.607574</td>
<td>8</td>
<td>0.4727104</td>
<td>21.60757</td>
<td>6.324123</td>
<td>3</td>
<td>0.09686277</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs61792225</td>
<td>4</td>
<td>85526</td>
<td>0.1739560</td>
<td>C</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.7963943</td>
<td>8.833127</td>
<td>8</td>
<td>0.3565683</td>
<td>22.83313</td>
<td>7.549675</td>
<td>3</td>
<td>0.05629572</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋱</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
<td>⋮</td>
</tr>
<tr class="even">
<td>rs6834433</td>
<td>4</td>
<td>100294905</td>
<td>0.2077530</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8712175</td>
<td>13.430376</td>
<td>8</td>
<td>0.0978747603</td>
<td>27.43038</td>
<td>12.1469250</td>
<td>3</td>
<td>6.896436e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs6857143</td>
<td>4</td>
<td>100294928</td>
<td>0.2077530</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9057906</td>
<td>13.365897</td>
<td>8</td>
<td>0.0998650553</td>
<td>27.36590</td>
<td>12.0824435</td>
<td>3</td>
<td>7.106014e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs6834464</td>
<td>4</td>
<td>100294945</td>
<td>0.2077530</td>
<td>T</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8381863</td>
<td>13.759848</td>
<td>8</td>
<td>0.0882436578</td>
<td>27.75985</td>
<td>12.4763917</td>
<td>3</td>
<td>5.917295e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs13121469</td>
<td>4</td>
<td>100295047</td>
<td>0.1172960</td>
<td>C</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.4026174</td>
<td>26.646167</td>
<td>8</td>
<td>0.0008136034</td>
<td>40.64617</td>
<td>25.3627149</td>
<td>3</td>
<td>1.296593e-05</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs56279505</td>
<td>4</td>
<td>100295240</td>
<td>0.0964215</td>
<td>T</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8475897</td>
<td>31.241304</td>
<td>8</td>
<td>0.0001272647</td>
<td>45.24130</td>
<td>29.9578521</td>
<td>3</td>
<td>1.408519e-06</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs1121534</td>
<td>4</td>
<td>100295415</td>
<td>0.2087480</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.8676112</td>
<td>13.834399</td>
<td>8</td>
<td>0.0861851697</td>
<td>27.83440</td>
<td>12.5509449</td>
<td>3</td>
<td>5.715560e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs6827898</td>
<td>4</td>
<td>100295863</td>
<td>0.1172960</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.3756755</td>
<td>24.804186</td>
<td>8</td>
<td>0.0016778555</td>
<td>38.80419</td>
<td>23.5207303</td>
<td>3</td>
<td>3.144944e-05</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs10030511</td>
<td>4</td>
<td>100296248</td>
<td>0.4473160</td>
<td>C</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.5111428</td>
<td>6.108862</td>
<td>8</td>
<td>0.6350390678</td>
<td>20.10886</td>
<td>4.8254096</td>
<td>3</td>
<td>1.850371e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs10032906</td>
<td>4</td>
<td>100296355</td>
<td>0.2067590</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9844021</td>
<td>16.448897</td>
<td>8</td>
<td>0.0363875630</td>
<td>30.44890</td>
<td>15.1654448</td>
<td>3</td>
<td>1.680586e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs34980886</td>
<td>4</td>
<td>100296402</td>
<td>0.1172960</td>
<td>T</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.3479156</td>
<td>24.096953</td>
<td>8</td>
<td>0.0022075521</td>
<td>38.09695</td>
<td>22.8135003</td>
<td>3</td>
<td>4.416375e-05</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs10000067</td>
<td>4</td>
<td>100296476</td>
<td>0.2067590</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9678549</td>
<td>16.609195</td>
<td>8</td>
<td>0.0344457602</td>
<td>30.60920</td>
<td>15.3257420</td>
<td>3</td>
<td>1.558415e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs76088139</td>
<td>4</td>
<td>100296678</td>
<td>0.2067590</td>
<td>C</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9823261</td>
<td>16.046919</td>
<td>8</td>
<td>0.0417134522</td>
<td>30.04692</td>
<td>14.7634672</td>
<td>3</td>
<td>2.030356e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs35208813</td>
<td>4</td>
<td>100296684</td>
<td>0.4483100</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.4735511</td>
<td>5.846655</td>
<td>8</td>
<td>0.6644040158</td>
<td>19.84666</td>
<td>4.5632037</td>
<td>3</td>
<td>2.067215e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs35796885</td>
<td>4</td>
<td>100296748</td>
<td>0.4483100</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.4841398</td>
<td>6.394731</td>
<td>8</td>
<td>0.6031062592</td>
<td>20.39473</td>
<td>5.1112786</td>
<td>3</td>
<td>1.638278e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs12651165</td>
<td>4</td>
<td>100296791</td>
<td>0.2067590</td>
<td>C</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9046283</td>
<td>16.548481</td>
<td>8</td>
<td>0.0351695859</td>
<td>30.54848</td>
<td>15.2650294</td>
<td>3</td>
<td>1.603614e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs66503521</td>
<td>4</td>
<td>100297205</td>
<td>0.2067590</td>
<td>C</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9029744</td>
<td>16.037486</td>
<td>8</td>
<td>0.0418467104</td>
<td>30.03749</td>
<td>14.7540322</td>
<td>3</td>
<td>2.039379e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs12502498</td>
<td>4</td>
<td>100297551</td>
<td>0.3240560</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.4844888</td>
<td>5.787124</td>
<td>8</td>
<td>0.6710632139</td>
<td>19.78712</td>
<td>4.5036703</td>
<td>3</td>
<td>2.119631e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs28818226</td>
<td>4</td>
<td>100297591</td>
<td>0.2067590</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9857570</td>
<td>16.463681</td>
<td>8</td>
<td>0.0362042963</td>
<td>30.46368</td>
<td>15.1802287</td>
<td>3</td>
<td>1.668932e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs9991913</td>
<td>4</td>
<td>100297896</td>
<td>0.2067590</td>
<td>G</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9932682</td>
<td>16.589447</td>
<td>8</td>
<td>0.0346796579</td>
<td>30.58945</td>
<td>15.3059960</td>
<td>3</td>
<td>1.572975e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs9992022</td>
<td>4</td>
<td>100297998</td>
<td>0.2067590</td>
<td>G</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9696586</td>
<td>16.470744</td>
<td>8</td>
<td>0.0361170551</td>
<td>30.47074</td>
<td>15.1872930</td>
<td>3</td>
<td>1.663391e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs13110291</td>
<td>4</td>
<td>100298393</td>
<td>0.1182900</td>
<td>A</td>
<td>G</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.3829837</td>
<td>23.222449</td>
<td>8</td>
<td>0.0030900849</td>
<td>37.22245</td>
<td>21.9389962</td>
<td>3</td>
<td>6.716566e-05</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs56899508</td>
<td>4</td>
<td>100298398</td>
<td>0.1182900</td>
<td>G</td>
<td>T</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.3767382</td>
<td>23.128751</td>
<td>8</td>
<td>0.0032028187</td>
<td>37.12875</td>
<td>21.8452984</td>
<td>3</td>
<td>7.024885e-05</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs9994612</td>
<td>4</td>
<td>100298399</td>
<td>0.2067590</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9960079</td>
<td>16.491560</td>
<td>8</td>
<td>0.0358610431</td>
<td>30.49156</td>
<td>15.2081083</td>
<td>3</td>
<td>1.647172e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td><span style="white-space:pre-wrap">rs283406 </span></td>
<td>4</td>
<td>100298471</td>
<td>0.0894632</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.2162775</td>
<td>1.778214</td>
<td>8</td>
<td>0.9870725654</td>
<td>15.77821</td>
<td>0.4947615</td>
<td>3</td>
<td>9.200408e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs10017136</td>
<td>4</td>
<td>100298681</td>
<td>0.2067590</td>
<td>A</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9678550</td>
<td>16.543299</td>
<td>8</td>
<td>0.0352320187</td>
<td>30.54330</td>
<td>15.2598444</td>
<td>3</td>
<td>1.607534e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs9997820</td>
<td>4</td>
<td>100299450</td>
<td>0.4502980</td>
<td>G</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.4744628</td>
<td>6.772480</td>
<td>8</td>
<td>0.5613676486</td>
<td>20.77248</td>
<td>5.4890277</td>
<td>3</td>
<td>1.392964e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs9997653</td>
<td>4</td>
<td>100299453</td>
<td>0.3260440</td>
<td>C</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.4702161</td>
<td>5.658205</td>
<td>8</td>
<td>0.6854562084</td>
<td>19.65821</td>
<td>4.3747501</td>
<td>3</td>
<td>2.237381e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs1908962</td>
<td>4</td>
<td>100299641</td>
<td>0.4483100</td>
<td>C</td>
<td>A</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.5317039</td>
<td>6.267869</td>
<td>8</td>
<td>0.6172541670</td>
<td>20.26787</td>
<td>4.9844168</td>
<td>3</td>
<td>1.729418e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="even">
<td>rs1908963</td>
<td>4</td>
<td>100299664</td>
<td>0.2067590</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.9495890</td>
<td>16.835809</td>
<td>8</td>
<td>0.0318649312</td>
<td>30.83581</td>
<td>15.5523550</td>
<td>3</td>
<td>1.400596e-03</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
<tr class="odd">
<td>rs1837932</td>
<td>4</td>
<td>100299978</td>
<td>0.4483100</td>
<td>T</td>
<td>C</td>
<td>F1</td>
<td>~</td>
<td>SNP</td>
<td>6</td>
<td>⋯</td>
<td>0.5111001</td>
<td>6.685218</td>
<td>8</td>
<td>0.5709443237</td>
<td>20.68522</td>
<td>5.4017663</td>
<td>3</td>
<td>1.446336e-01</td>
<td>0</td>
<td><span style="white-space:pre-wrap">lavaan-&gt;lav_lavaan_step02_options(): the following argument(s) override(s) the options in slotOptions: se</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="practice-section-anthropometric-traits" class="level3" data-number="1.0.42">
<h3 data-number="1.0.42" class="anchored" data-anchor-id="practice-section-anthropometric-traits"><span class="header-section-number">1.0.42</span> 31. Practice Section: Anthropometric Traits</h3>
<p>The workshop also provides an additional LDSC object for anthropometric traits.</p>
<p>These include:</p>
<ul>
<li>BMI: Body Mass Index</li>
<li>WHR: Waist-Hip Ratio</li>
<li>Waist: Waist Circumference</li>
<li>Hip: Hip Circumference</li>
<li>CO: Childhood Obesity</li>
<li>Height: Height</li>
<li>BL: Birth Length</li>
<li>BW: Birth Weight</li>
<li>IHC: Infant Head Circumference</li>
</ul>
<p>The goal is to practice specifying your own model.</p>
<div id="40f937fd-a1a9-4990-b0f5-185072ef2a4b" class="cell" data-execution_count="39">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb35-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load anthropometric LDSC object</span></span>
<span id="cb35-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Anthro_LDSC.RData"</span>)</span>
<span id="cb35-3"></span>
<span id="cb35-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define covariance structure</span></span>
<span id="cb35-5">covstruc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> anthro</span>
<span id="cb35-6"></span>
<span id="cb35-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Check available traits</span></span>
<span id="cb35-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(anthro<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>S)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<style>
.list-inline {list-style: none; margin:0; padding: 0}
.list-inline>li {display: inline-block}
.list-inline>li:not(:last-child)::after {content: "\00b7"; padding: 0 .5ex}
</style>
<ol class="list-inline"><li>'BMI'</li><li>'WHR'</li><li>'CO'</li><li>'Waist'</li><li>'Hip'</li><li>'Height'</li><li>'IHC'</li><li>'BL'</li><li>'BW'</li></ol>
</div>
</div>
</section>
<section id="example-anthropometric-factor-model" class="level3" data-number="1.0.43">
<h3 data-number="1.0.43" class="anchored" data-anchor-id="example-anthropometric-factor-model"><span class="header-section-number">1.0.43</span> 32. Example Anthropometric Factor Model</h3>
<p>One possible model is a general body-size factor.</p>
<p>This is only an example. In real research, you should write down your model before running it.</p>
<div id="98128b99-7865-4700-9383-a61a17a5013f" class="cell" data-execution_count="41">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb36" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb36-1">Your.Model <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;">"</span></span>
<span id="cb36-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">BodySize =~ BMI + WHR + Waist + Hip</span></span>
<span id="cb36-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb36-4"></span>
<span id="cb36-5">std.lv <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="cb36-6"></span>
<span id="cb36-7">YourResults <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">usermodel</span>(</span>
<span id="cb36-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">covstruc =</span> covstruc,</span>
<span id="cb36-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> Your.Model,</span>
<span id="cb36-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">std.lv =</span> std.lv</span>
<span id="cb36-11">)</span>
<span id="cb36-12"></span>
<span id="cb36-13">YourResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>results</span>
<span id="cb36-14">YourResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>modelfit</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Running primary model"
[1] "Calculating Standardized Results"
[1] "Calculating SRMR"
elapsed 
  0.099 
[1] "The S matrix was smoothed prior to model estimation due to a non-positive definite matrix. The largest absolute difference in a cell between the smoothed and non-smoothed matrix was  5.03885789198688e-05 As a result of the smoothing, the largest Z-statistic change for the genetic covariances was  0.00627650037966632 . We recommend setting the smooth_check argument to true if you are going to run a multivariate GWAS."</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 9 × 9</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">lhs</th>
<th data-quarto-table-cell-role="th" scope="col">op</th>
<th data-quarto-table-cell-role="th" scope="col">rhs</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_Est</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_All</th>
<th data-quarto-table-cell-role="th" scope="col">p_value</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>BodySize</td>
<td>=~</td>
<td><span style="white-space:pre-wrap">BMI </span></td>
<td>0.32835242</td>
<td>0.00834346434861948</td>
<td>0.9261942</td>
<td>0.0235346832851601</td>
<td>0.9261941</td>
<td><span style="white-space:pre-wrap">&lt; 5e-300 </span></td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>BodySize</td>
<td>=~</td>
<td>WHR</td>
<td>0.17364843</td>
<td>0.00899442936403122</td>
<td>0.5823406</td>
<td>0.0301633569935819</td>
<td>0.5823405</td>
<td>4.76178089813194e-83</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>BodySize</td>
<td>=~</td>
<td><span style="white-space:pre-wrap">Waist </span></td>
<td>0.37150337</td>
<td>0.00849900513137077</td>
<td>1.0554343</td>
<td>0.0241454997322284</td>
<td>1.0554343</td>
<td><span style="white-space:pre-wrap">&lt; 5e-300 </span></td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>BodySize</td>
<td>=~</td>
<td>Hip</td>
<td>0.29921533</td>
<td>0.00998707625847693</td>
<td>0.8166573</td>
<td>0.0272580315696167</td>
<td>0.8166573</td>
<td>3.23530305105103e-197</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>BMI</td>
<td>~~</td>
<td>BMI</td>
<td>0.01786761</td>
<td>0.00214989324612072</td>
<td>0.1421646</td>
<td>0.0171056871098916</td>
<td>0.1421646</td>
<td>9.49574545542005e-17</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">9</th>
<td>WHR</td>
<td>~~</td>
<td>WHR</td>
<td>0.05876384</td>
<td>0.00500826060659902</td>
<td>0.6608797</td>
<td>0.0563247279072853</td>
<td>0.6608795</td>
<td>8.59540394910649e-32</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">8</th>
<td>Waist</td>
<td>~~</td>
<td>Waist</td>
<td>-0.01411697</td>
<td>0.0014484156789879</td>
<td>-0.1139415</td>
<td>0.0116904301220693</td>
<td>-0.1139415</td>
<td>1.90955940051609e-22</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">7</th>
<td>Hip</td>
<td>~~</td>
<td>Hip</td>
<td>0.04471200</td>
<td>0.00409589113627207</td>
<td>0.3330708</td>
<td>0.0305112937271513</td>
<td>0.3330708</td>
<td>9.6335396382315e-28</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>BodySize</td>
<td>~~</td>
<td>BodySize</td>
<td>1.00000000</td>
<td></td>
<td>1.0000000</td>
<td></td>
<td>1.0000000</td>
<td>NA</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">df</th>
<th data-quarto-table-cell-role="th" scope="col">p_chisq</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">CFI</th>
<th data-quarto-table-cell-role="th" scope="col">SRMR</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">df</th>
<td>4808.273</td>
<td>2</td>
<td>0</td>
<td>4824.273</td>
<td>0.9790462</td>
<td>0.07075376</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="example-two-factor-model" class="level3" data-number="1.0.44">
<h3 data-number="1.0.44" class="anchored" data-anchor-id="example-two-factor-model"><span class="header-section-number">1.0.44</span> 33. Example Two-Factor Model</h3>
<p>We may hypothesize that body mass and early growth are partly distinct genetic dimensions.</p>
<p>For example:</p>
<ul>
<li>AdultBody: BMI, WHR, Waist, Hip</li>
<li>EarlyGrowth: BL, BW, IHC</li>
</ul>
<div id="9a26d22c-a737-4358-ac2c-05c8d48cdd36" class="cell" data-execution_count="42">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb38" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb38-1">TwoFactor.Model <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;">"</span></span>
<span id="cb38-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">AdultBody =~ BMI + WHR + Waist + Hip</span></span>
<span id="cb38-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">EarlyGrowth =~ BL + BW + IHC</span></span>
<span id="cb38-4"></span>
<span id="cb38-5"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">AdultBody ~~ EarlyGrowth</span></span>
<span id="cb38-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb38-7"></span>
<span id="cb38-8">TwoFactorResults <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">usermodel</span>(</span>
<span id="cb38-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">covstruc =</span> covstruc,</span>
<span id="cb38-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> TwoFactor.Model,</span>
<span id="cb38-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">std.lv =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb38-12">)</span>
<span id="cb38-13"></span>
<span id="cb38-14">TwoFactorResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>results</span>
<span id="cb38-15">TwoFactorResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>modelfit</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Running primary model"
[1] "Calculating Standardized Results"
[1] "Calculating SRMR"
elapsed 
  0.139 
[1] "The S matrix was smoothed prior to model estimation due to a non-positive definite matrix. The largest absolute difference in a cell between the smoothed and non-smoothed matrix was  7.68229238531509e-05 As a result of the smoothing, the largest Z-statistic change for the genetic covariances was  0.00971267593380176 . We recommend setting the smooth_check argument to true if you are going to run a multivariate GWAS."</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 17 × 9</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">lhs</th>
<th data-quarto-table-cell-role="th" scope="col">op</th>
<th data-quarto-table-cell-role="th" scope="col">rhs</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_Est</th>
<th data-quarto-table-cell-role="th" scope="col">Unstand_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype</th>
<th data-quarto-table-cell-role="th" scope="col">STD_Genotype_SE</th>
<th data-quarto-table-cell-role="th" scope="col">STD_All</th>
<th data-quarto-table-cell-role="th" scope="col">p_value</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td><span style="white-space:pre-wrap">AdultBody </span></td>
<td>=~</td>
<td><span style="white-space:pre-wrap">BMI </span></td>
<td>0.32355145</td>
<td>0.00848257151119238</td>
<td>0.9126525</td>
<td>0.0239270666230049</td>
<td>0.9126526</td>
<td><span style="white-space:pre-wrap">&lt; 5e-300 </span></td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>AdultBody</td>
<td>=~</td>
<td>WHR</td>
<td>0.17014707</td>
<td>0.00915015430923173</td>
<td>0.5705696</td>
<td>0.0306840495730172</td>
<td>0.5705696</td>
<td>3.52749230117905e-77</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td><span style="white-space:pre-wrap">AdultBody </span></td>
<td>=~</td>
<td><span style="white-space:pre-wrap">Waist </span></td>
<td>0.37262394</td>
<td>0.00839616539135095</td>
<td>1.0585040</td>
<td>0.0238508087911616</td>
<td>1.0585043</td>
<td><span style="white-space:pre-wrap">&lt; 5e-300 </span></td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>AdultBody</td>
<td>=~</td>
<td>Hip</td>
<td>0.30767486</td>
<td>0.00991987368769025</td>
<td>0.8397060</td>
<td>0.0270733262889365</td>
<td>0.8397059</td>
<td>3.27994599611528e-211</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">10</th>
<td>EarlyGrowth</td>
<td>=~</td>
<td>BL</td>
<td>0.31883086</td>
<td>0.0424505344230068</td>
<td>0.7863983</td>
<td>0.104704413507432</td>
<td>0.7863989</td>
<td>5.88371366564811e-14</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">11</th>
<td>EarlyGrowth</td>
<td>=~</td>
<td>BW</td>
<td>0.25182147</td>
<td>0.0369779692381788</td>
<td>0.7456392</td>
<td>0.109491090900721</td>
<td>0.7456389</td>
<td>9.75711480693518e-12</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">12</th>
<td>EarlyGrowth</td>
<td>=~</td>
<td>IHC</td>
<td>0.38776135</td>
<td>0.0639504168355385</td>
<td>0.8067723</td>
<td>0.133054274151609</td>
<td>0.8067722</td>
<td>1.33216727234899e-09</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>AdultBody</td>
<td>~~</td>
<td>EarlyGrowth</td>
<td>0.20561960</td>
<td>0.0457670518741615</td>
<td>0.2056203</td>
<td>0.0457670449740265</td>
<td>0.2056203</td>
<td>7.03116016834168e-06</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">8</th>
<td>BMI</td>
<td>~~</td>
<td>BMI</td>
<td>0.02099732</td>
<td>0.00236172074867183</td>
<td>0.1670651</td>
<td>0.0187911396306323</td>
<td>0.1670652</td>
<td>6.07311168507216e-19</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">17</th>
<td>WHR</td>
<td>~~</td>
<td>WHR</td>
<td>0.05997650</td>
<td>0.00508748828560331</td>
<td>0.6744501</td>
<td>0.0572099863458111</td>
<td>0.6744503</td>
<td>4.44686078822693e-32</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">16</th>
<td>Waist</td>
<td>~~</td>
<td>Waist</td>
<td>-0.01492436</td>
<td>0.00155917314029345</td>
<td>-0.1204312</td>
<td>0.0125816586271371</td>
<td>-0.1204313</td>
<td>1.04884008907025e-21</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">14</th>
<td>Hip</td>
<td>~~</td>
<td>Hip</td>
<td>0.03959078</td>
<td>0.00385032587902093</td>
<td>0.2948940</td>
<td>0.0286792741025182</td>
<td>0.2948940</td>
<td>8.45512132535067e-25</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">15</th>
<td>IHC</td>
<td>~~</td>
<td>IHC</td>
<td>0.08065102</td>
<td>0.058447583363325</td>
<td>0.3491186</td>
<td>0.253010103779767</td>
<td>0.3491186</td>
<td>0.167621642770187</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">7</th>
<td>BL</td>
<td>~~</td>
<td>BL</td>
<td>0.06272152</td>
<td>0.0309055815553739</td>
<td>0.3815762</td>
<td>0.188018927129747</td>
<td>0.3815767</td>
<td>0.0424118546489747</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">9</th>
<td>BW</td>
<td>~~</td>
<td>BW</td>
<td>0.05064431</td>
<td>0.0212845979481534</td>
<td>0.4440231</td>
<td>0.186611198922835</td>
<td>0.4440227</td>
<td>0.0173414200434353</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>AdultBody</td>
<td>~~</td>
<td>AdultBody</td>
<td>1.00000000</td>
<td></td>
<td>1.0000000</td>
<td></td>
<td>1.0000000</td>
<td>NA</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">13</th>
<td>EarlyGrowth</td>
<td>~~</td>
<td>EarlyGrowth</td>
<td>1.00000000</td>
<td></td>
<td>1.0000000</td>
<td></td>
<td>1.0000000</td>
<td>NA</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">df</th>
<th data-quarto-table-cell-role="th" scope="col">p_chisq</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">CFI</th>
<th data-quarto-table-cell-role="th" scope="col">SRMR</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">df</th>
<td>4994.695</td>
<td>13</td>
<td>0</td>
<td>5024.695</td>
<td>0.9822088</td>
<td>0.09017272</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="comparing-models" class="level3" data-number="1.0.45">
<h3 data-number="1.0.45" class="anchored" data-anchor-id="comparing-models"><span class="header-section-number">1.0.45</span> 34. Comparing Models</h3>
<p>We can compare models using fit statistics such as AIC, CFI, and SRMR.</p>
<p>Lower AIC suggests a better-fitting model among competing models.</p>
<p>Higher CFI and lower SRMR suggest better absolute fit.</p>
<div id="72b9b175-5fa2-4c91-868d-da6e01c4ffb9" class="cell" data-execution_count="43">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb40" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb40-1">YourResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>modelfit</span>
<span id="cb40-2">TwoFactorResults<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>modelfit</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">df</th>
<th data-quarto-table-cell-role="th" scope="col">p_chisq</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">CFI</th>
<th data-quarto-table-cell-role="th" scope="col">SRMR</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">df</th>
<td>4808.273</td>
<td>2</td>
<td>0</td>
<td>4824.273</td>
<td>0.9790462</td>
<td>0.07075376</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">chisq</th>
<th data-quarto-table-cell-role="th" scope="col">df</th>
<th data-quarto-table-cell-role="th" scope="col">p_chisq</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
<th data-quarto-table-cell-role="th" scope="col">CFI</th>
<th data-quarto-table-cell-role="th" scope="col">SRMR</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">df</th>
<td>4994.695</td>
<td>13</td>
<td>0</td>
<td>5024.695</td>
<td>0.9822088</td>
<td>0.09017272</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="important-practical-advice" class="level3" data-number="1.0.46">
<h3 data-number="1.0.46" class="anchored" data-anchor-id="important-practical-advice"><span class="header-section-number">1.0.46</span> 35. Important Practical Advice</h3>
<p>Genomic SEM is flexible, but this flexibility should be used carefully.</p>
<p>Do not simply try many models until one gives a significant result.</p>
<p>A better workflow is:</p>
<ol type="1">
<li>Define your research question.</li>
<li>Write down your hypothesized model.</li>
<li>Run the model.</li>
<li>Check model fit.</li>
<li>Interpret parameters cautiously.</li>
<li>If using data-driven exploration, clearly report it as exploratory.</li>
</ol>
<p>This is especially important in multivariate genetic modeling because many reasonable models may appear plausible.</p>
</section>
<section id="summary" class="level3" data-number="1.0.47">
<h3 data-number="1.0.47" class="anchored" data-anchor-id="summary"><span class="header-section-number">1.0.47</span> 36. Summary</h3>
<p>In this tutorial, we covered the main concepts behind multivariate genetic analysis using Genomic SEM.</p>
<p>We learned that complex traits are highly polygenic and that LD Score Regression uses the relationship between LD score and GWAS signal to estimate SNP heritability.</p>
<p>We then extended this idea to genetic covariance and genetic correlation across traits.</p>
<p>Finally, we introduced Genomic SEM as a framework for fitting structural models to genetic covariance matrices and for running multivariate GWAS on latent genetic factors.</p>
<p>The key idea is simple but powerful:</p>
<blockquote class="blockquote">
<p>Instead of studying each trait separately, Genomic SEM allows us to model shared and trait-specific genetic architecture across multiple traits.</p>
</blockquote>
<p>This makes it especially useful for psychiatric, behavioral, anthropometric, and medical traits where genetic overlap is common.</p>
</section>
<section id="key-takeaways" class="level3" data-number="1.0.48">
<h3 data-number="1.0.48" class="anchored" data-anchor-id="key-takeaways"><span class="header-section-number">1.0.48</span> 37. Key Takeaways</h3>
<ul>
<li>Complex traits are usually highly polygenic.</li>
<li>LD scores summarize how much LD each SNP has with nearby SNPs.</li>
<li>LD Score Regression estimates SNP heritability from GWAS summary statistics.</li>
<li>Cross-trait LD Score Regression estimates genetic covariance and genetic correlation.</li>
<li>Genomic SEM fits structural equation models to genetic covariance matrices.</li>
<li>A common factor model can capture shared genetic liability across traits.</li>
<li>Multivariate GWAS can test SNP effects on latent genetic factors.</li>
<li>QSNP tests whether SNP effects are consistent with the common factor model or show trait-specific heterogeneity.</li>
</ul>


</section>
</section>

 ]]></description>
  <category>Statistical Genetics</category>
  <category>GWAS</category>
  <category>Genomic SEM</category>
  <category>Multivariate Analysis</category>
  <guid>https://bntechie.github.io/tutorials/multivariate_concepts/genomicSEM.html</guid>
  <pubDate>Mon, 27 Jul 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/multivariate_concepts/images/genomic-sem-factor.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Heritability and Genetic Correlation: From First Principles to Summary Statistics</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/Heritability_genetic_correlation/Heritability_and_Genetic_Correlation.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/Heritability_genetic_correlation/images/heritability-duality.svg" alt="Two scatter plots with fitted regression lines: HE regression plotting phenotype cross-products against relatedness, and LDSC plotting chi-squared statistics against LD score -- both recovering heritability as the slope" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The core duality this tutorial builds toward: HE regression works in the space of individuals (relatedness), LDSC works in the space of markers (LD score) – but in both, heritability is just a regression slope. These panels are plotted from the tutorial’s own simulated data.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">Heritability</span> <span class="tag">LDSC</span> <span class="tag">GREML</span> <span class="tag">R</span></p>
</div>
<p>Every quantitative genetics question eventually runs into the same two words: <strong>heritability</strong> and <strong>genetic correlation</strong>. How much of height is genetic? Do depression and obesity share genetic causes? Is a GWAS signal confounded by population structure?</p>
<p>Answering any of these requires estimating variance and covariance — not of the phenotype itself, but of its <em>genetic component</em>. This tutorial builds that machinery from the ground up: starting with individual-level methods you could run by hand on a handful of relatives, and ending with the summary-statistics methods (LD Score Regression) that power essentially every modern GWAS consortium paper.</p>
<blockquote class="blockquote">
<p><strong>What you’ll learn</strong></p>
<ul>
<li>What “heritability” actually means — and why there are three different definitions</li>
<li>How to estimate heritability from relatives, using Haseman-Elston regression</li>
<li>Why binary disease traits need special handling (the liability threshold model)</li>
<li>How LD Score Regression estimates heritability from GWAS summary statistics alone</li>
<li>What genetic correlation is, and the four different reasons two traits can share genetic architecture</li>
<li>The practical pitfalls that make genetic correlation estimates misleading if you’re not careful</li>
</ul>
</blockquote>
<section id="why-do-we-need-a-formal-definition-of-heritability-at-all" class="level2" data-number="0.1">
<h2 data-number="0.1" class="anchored" data-anchor-id="why-do-we-need-a-formal-definition-of-heritability-at-all"><span class="header-section-number">0.1</span> Why Do We Need a Formal Definition of Heritability at All?</h2>
<p>Francis Galton noticed over a century ago that relatives resemble each other more than random pairs of people, and that identical twins resemble each other more than fraternal twins. A large meta-analysis of fifty years of twin studies later put a number on this: an average heritability estimate of 49% across thousands of traits, with 69% of studies supporting a purely additive genetic model (Polderman et al., 2015).</p>
<p>But “heritability” turns out to be a slippery word. Before we can estimate it, we need to agree on exactly what quantity we’re estimating.</p>
</section>
<section id="part-1-three-definitions-of-heritability" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Part 1 — Three Definitions of Heritability</h1>
<p>An <strong>estimand</strong> is the true underlying population parameter we’re actually trying to estimate. It sounds like a pedantic distinction, but different heritability methods target genuinely different estimands — and comparing numbers across methods without realizing this is a common source of confusion.</p>
<section id="fixed-effect-realised-variance" class="level2" data-number="1.1">
<h2 data-number="1.1" class="anchored" data-anchor-id="fixed-effect-realised-variance"><span class="header-section-number">1.1</span> Fixed-Effect Realised Variance</h2>
<p><img src="https://latex.codecogs.com/png.latex?y%20=%20X%5Cbeta%20+%20%5Cvarepsilon,%20%5Cqquad%20h%5E2%20:=%20%5Cfrac%7B%5Ctext%7BVar%7D(X%5Cbeta)%7D%7B%5Ctext%7BVar%7D(y)%7D"></p>
<p>This asks: of the phenotypic variance in <em>this specific sample</em>, how much is explained by the genotypes we actually observed? It’s a property of the realized data, not an abstract population parameter.</p>
</section>
<section id="random-individual-expected-variance" class="level2" data-number="1.2">
<h2 data-number="1.2" class="anchored" data-anchor-id="random-individual-expected-variance"><span class="header-section-number">1.2</span> Random-Individual Expected Variance</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BCov%7D(y)%20=%20%5Csigma_g%5E2%20K%20+%20%5Csigma_e%5E2%20I%20%5Cquad%20(K%20=%20%5Ctext%7BGRM%7D),%20%5Cqquad%20h%5E2%20:=%20%5Cfrac%7B%5Csigma_g%5E2%7D%7B%5Csigma_g%5E2%20+%20%5Csigma_e%5E2%7D"></p>
<p>Here, genetic effects are treated as random draws from a distribution, and <img src="https://latex.codecogs.com/png.latex?K"> — the <strong>Genetic Relationship Matrix (GRM)</strong> — captures how genetically similar each pair of individuals is. This is the estimand targeted by methods like <strong>GREML/GCTA</strong> (Part 3).</p>
</section>
<section id="random-marker-expected-variance" class="level2" data-number="1.3">
<h2 data-number="1.3" class="anchored" data-anchor-id="random-marker-expected-variance"><span class="header-section-number">1.3</span> Random-Marker Expected Variance</h2>
<p><img src="https://latex.codecogs.com/png.latex?y%20=%20X%5Cbeta%20+%20%5Cvarepsilon,%20%5Cqquad%20%5Cbeta%20%5Csim%20%5Cleft%5B0,%20%5Cfrac%7B%5Csigma_g%5E2%7D%7BM%7D%5Cright%5D,%20%5Cquad%20%5Cvarepsilon%20%5Csim%20%5B0,%201-%5Csigma_g%5E2%5D"></p>
<p>Here it’s the SNP <em>effects</em> that are random, each drawn with variance <img src="https://latex.codecogs.com/png.latex?%5Csigma_g%5E2/M"> (spread evenly across <img src="https://latex.codecogs.com/png.latex?M"> SNPs). The estimand is <img src="https://latex.codecogs.com/png.latex?%5Csigma_g%5E2"> directly. This is the estimand targeted by <strong>LD Score Regression</strong> (Part 5).</p>
</section>
<section id="why-this-distinction-matters-in-practice" class="level2" data-number="1.4">
<h2 data-number="1.4" class="anchored" data-anchor-id="why-this-distinction-matters-in-practice"><span class="header-section-number">1.4</span> Why This Distinction Matters in Practice</h2>
<p>GREML and LDSC are both routinely described as estimating “SNP heritability,” but they’re formally targeting different estimands under different assumptions about what’s random (individuals vs.&nbsp;markers). In practice they tend to agree well for polygenic traits with good data — but when they disagree, the difference isn’t necessarily a bug in one of the methods; it can reflect which estimand each one is actually built to target.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>“Heritability” has at least three distinct formal definitions, differing in what’s treated as random (nothing, individuals, or markers).</li>
<li>GREML targets the random-individual estimand; LD Score Regression targets the random-marker estimand.</li>
<li>Keep this in mind before treating heritability estimates from different methods as directly interchangeable.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-2-haseman-elston-regression-heritability-from-first-principles" class="level1" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Part 2 — Haseman-Elston Regression: Heritability from First Principles</h1>
<p>Before GWAS existed, before genome-wide SNP arrays existed, geneticists were already estimating heritability — from relatives. <strong>Haseman-Elston (HE) regression</strong>, developed by J.K. Haseman and R.C. Elston in 1972, is the conceptual ancestor of nearly every method in this tutorial, including LD Score Regression itself.</p>
<section id="the-core-premise" class="level2" data-number="2.1">
<h2 data-number="2.1" class="anchored" data-anchor-id="the-core-premise"><span class="header-section-number">2.1</span> The Core Premise</h2>
<blockquote class="blockquote">
<p>If a trait is influenced by genetics, relatives who are more genetically similar should have more similar phenotypes.</p>
</blockquote>
<p>HE regression turns this intuition into a simple <strong>ordinary least squares (OLS)</strong> regression — no maximum likelihood, no iterative optimization, just a linear regression of phenotypic similarity on genetic similarity.</p>
</section>
<section id="setting-up-the-model" class="level2" data-number="2.2">
<h2 data-number="2.2" class="anchored" data-anchor-id="setting-up-the-model"><span class="header-section-number">2.2</span> Setting Up the Model</h2>
<p>Let <img src="https://latex.codecogs.com/png.latex?y_i"> and <img src="https://latex.codecogs.com/png.latex?y_j"> be the (mean-centered) phenotypes of individuals <img src="https://latex.codecogs.com/png.latex?i"> and <img src="https://latex.codecogs.com/png.latex?j">, so <img src="https://latex.codecogs.com/png.latex?E%5By%5D=0">. The basic additive model is <img src="https://latex.codecogs.com/png.latex?y_i%20=%20g_i%20+%20e_i">, giving:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(y_i)%20=%20%5Csigma_g%5E2%20+%20%5Csigma_e%5E2"></p>
<p>Assuming no shared environment, phenotypic covariance between two relatives is driven entirely by the proportion of genome they share identical by descent, <img src="https://latex.codecogs.com/png.latex?%5Cpi_%7Bi,j%7D">:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BCov%7D(y_i,%20y_j)%20=%20%5Cpi_%7Bi,j%7D%5C,%5Csigma_g%5E2"></p>
</section>
<section id="version-1-1972-squared-differences" class="level2" data-number="2.3">
<h2 data-number="2.3" class="anchored" data-anchor-id="version-1-1972-squared-differences"><span class="header-section-number">2.3</span> Version 1 (1972): Squared Differences</h2>
<p>Haseman and Elston’s original approach measured phenotypic similarity using the squared difference <img src="https://latex.codecogs.com/png.latex?D_%7Bi,j%7D%20=%20(y_i%20-%20y_j)%5E2">. Expanding and substituting the variance/covariance definitions above:</p>
<p><img src="https://latex.codecogs.com/png.latex?E%5BD_%7Bi,j%7D%5D%20=%20%5Ctext%7BVar%7D(y_i)%20+%20%5Ctext%7BVar%7D(y_j)%20-%202%5C,%5Ctext%7BCov%7D(y_i,y_j)%20=%202(%5Csigma_g%5E2+%5Csigma_e%5E2)%20-%202%5Cpi_%7Bi,j%7D%5Csigma_g%5E2"></p>
<p>This gives a linear regression <img src="https://latex.codecogs.com/png.latex?D_%7Bi,j%7D%20=%20a%20+%20b%5C,%5Cpi_%7Bi,j%7D%20+%20%5Cvarepsilon">, where the intercept <img src="https://latex.codecogs.com/png.latex?a"> estimates <img src="https://latex.codecogs.com/png.latex?2(%5Csigma_g%5E2+%5Csigma_e%5E2)"> (twice total phenotypic variance) and the slope <img src="https://latex.codecogs.com/png.latex?b"> estimates <img src="https://latex.codecogs.com/png.latex?-2%5Csigma_g%5E2">. So: regress squared phenotypic differences on genetic relatedness, then divide the slope by <img src="https://latex.codecogs.com/png.latex?-2"> to recover <img src="https://latex.codecogs.com/png.latex?%5Csigma_g%5E2">.</p>
</section>
<section id="version-2-2000-cross-products-simpler-and-more-powerful" class="level2" data-number="2.4">
<h2 data-number="2.4" class="anchored" data-anchor-id="version-2-2000-cross-products-simpler-and-more-powerful"><span class="header-section-number">2.4</span> Version 2 (2000): Cross-Products — Simpler and More Powerful</h2>
<p>Elston and colleagues later proposed a cleaner alternative: use the <strong>cross-product</strong> of mean-centered phenotypes, <img src="https://latex.codecogs.com/png.latex?C_%7Bi,j%7D%20=%20y_i%20y_j">, instead of the squared difference.</p>
<p><strong>Why is this better?</strong> Squared differences mix together the covariance (the genetic signal we actually want) with each individual’s own variance (which includes environmental noise). Cross-products isolate the covariance directly. Since <img src="https://latex.codecogs.com/png.latex?E%5By_i%5D=E%5By_j%5D=0">:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BCov%7D(y_i,y_j)%20=%20E%5By_iy_j%5D%20-%20E%5By_i%5DE%5By_j%5D%20=%20E%5By_iy_j%5D"></p>
<p>so <img src="https://latex.codecogs.com/png.latex?E%5BC_%7Bi,j%7D%5D%20=%20%5Ctext%7BCov%7D(y_i,y_j)%20=%20%5Cpi_%7Bi,j%7D%5Csigma_g%5E2"> directly. This gives an even simpler regression:</p>
<p><img src="https://latex.codecogs.com/png.latex?C_%7Bi,j%7D%20=%20a%20+%20b%5C,%5Cpi_%7Bi,j%7D%20+%20%5Cvarepsilon"></p>
<p>Now the intercept is expected to be exactly zero (assuming no shared environment), and <strong>the slope <img src="https://latex.codecogs.com/png.latex?b"> estimates <img src="https://latex.codecogs.com/png.latex?%5Csigma_g%5E2"> directly</strong> — no dividing by <img src="https://latex.codecogs.com/png.latex?-2"> required.</p>
</section>
<section id="a-simulated-illustration" class="level2" data-number="2.5">
<h2 data-number="2.5" class="anchored" data-anchor-id="a-simulated-illustration"><span class="header-section-number">2.5</span> A Simulated Illustration</h2>
<div id="e6911a37" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T19:08:05.684062Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T19:08:05.672081Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T19:08:05.899182Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T19:08:05.891631Z&quot;}}" data-execution_count="1">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulate a simple additive-genetic scenario across pairs of relatives</span></span>
<span id="cb1-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;">1</span>)</span>
<span id="cb1-3">n_pairs <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;">2000</span></span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Relatedness (pi_ij): 0.5 for siblings, 0.25 for half-sibs/grandparent, etc.</span></span>
<span id="cb1-6">pi_ij <span class="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="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.125</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>), n_pairs, <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>
<span id="cb1-7">                 <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="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.25</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.25</span>))</span>
<span id="cb1-8"></span>
<span id="cb1-9">sigma_g2 <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.4</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true additive genetic variance</span></span>
<span id="cb1-10">sigma_e2 <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.6</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true environmental variance</span></span>
<span id="cb1-11"></span>
<span id="cb1-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulate mean-centered phenotype pairs consistent with this relatedness structure</span></span>
<span id="cb1-13">y_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;">rnorm</span>(n_pairs, <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;">sqrt</span>(sigma_g2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> sigma_e2))</span>
<span id="cb1-14">noise <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_pairs, <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;">sqrt</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> pi_ij) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> sigma_g2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> sigma_e2))</span>
<span id="cb1-15">y_j <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pi_ij <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> y_i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> noise   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># illustrative construction, not a full pedigree simulator</span></span>
<span id="cb1-16"></span>
<span id="cb1-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cross-product HE regression</span></span>
<span id="cb1-18">C_ij <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> y_i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> y_j</span>
<span id="cb1-19">he_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;">lm</span>(C_ij <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> pi_ij)</span>
<span id="cb1-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(he_fit)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># slope should recover something in the neighborhood of sigma_g2</span></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>
Call:
lm(formula = C_ij ~ pi_ij)

Residuals:
    Min      1Q  Median      3Q     Max 
-4.7523 -0.5138 -0.1174  0.3520 10.3084 

Coefficients:
            Estimate Std. Error t value Pr(&gt;|t|)    
(Intercept) -0.02636    0.03741  -0.705    0.481    
pi_ij        1.09987    0.13514   8.139 6.93e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.089 on 1998 degrees of freedom
Multiple R-squared:  0.03209,   Adjusted R-squared:  0.03161 
F-statistic: 66.24 on 1 and 1998 DF,  p-value: 6.93e-16</code></pre>
</div>
</div>
<p>This is a simplified illustration of the logic, not a full quantitative-genetics simulator (real HE regression is normally run on GRM values estimated from genome-wide SNP data, not a handful of discrete relatedness categories) — but it captures the essential mechanic: <strong>regress phenotype cross-products on genetic relatedness, and the slope is your heritability estimate.</strong></p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>HE regression turns “genetically-similar relatives resemble each other phenotypically” into a simple linear regression.</li>
<li>The original (1972) squared-difference version requires dividing the slope by <img src="https://latex.codecogs.com/png.latex?-2">.</li>
<li>The revised (2000) cross-product version is both simpler and more statistically powerful, because it isolates covariance without mixing in individual-level variance.</li>
<li>HE regression is the conceptual foundation for LD Score Regression, covered in Part 5.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-3-greml-gcta-and-the-genetic-relationship-matrix" class="level1" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> Part 3 — GREML, GCTA, and the Genetic Relationship Matrix</h1>
<p>HE regression works well conceptually, but modern genome-wide SNP data calls for a slightly different formalization: <strong>GREML</strong> (Genomic REstricted Maximum Likelihood), implemented in the widely-used <strong>GCTA</strong> software (Yang et al.).</p>
<section id="from-ols-to-a-mixed-model" class="level2" data-number="3.1">
<h2 data-number="3.1" class="anchored" data-anchor-id="from-ols-to-a-mixed-model"><span class="header-section-number">3.1</span> From OLS to a Mixed Model</h2>
<p>Instead of a simple linear regression, GREML fits a random-effects mixed model:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BCov%7D(y)%20=%20%5Csigma_g%5E2%20K%20+%20%5Csigma_e%5E2%20I"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?K"> is the <strong>Genetic Relationship Matrix (GRM)</strong> — the genome-wide analog of the pairwise relatedness <img src="https://latex.codecogs.com/png.latex?%5Cpi_%7Bi,j%7D"> from HE regression, but estimated directly from SNP genotypes rather than known pedigree relationships. This targets the <em>random-individual expected variance</em> estimand from Part 1: <img src="https://latex.codecogs.com/png.latex?h%5E2%20:=%20%5Csigma_g%5E2/(%5Csigma_g%5E2+%5Csigma_e%5E2)">.</p>
</section>
<section id="building-the-grm" class="level2" data-number="3.2">
<h2 data-number="3.2" class="anchored" data-anchor-id="building-the-grm"><span class="header-section-number">3.2</span> Building the GRM</h2>
<p>The GRM quantifies genetic similarity between every pair of individuals in a sample, estimated from genome-wide genotype data rather than known family relationships — which is what makes it applicable to unrelated individuals in large cohorts like biobanks, not just close relatives.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th></th>
<th>Person A</th>
<th>Person B</th>
<th>Person C</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>A</strong></td>
<td>1.00</td>
<td>0.10</td>
<td>0.02</td>
</tr>
<tr class="even">
<td><strong>B</strong></td>
<td>0.10</td>
<td>1.00</td>
<td>0.08</td>
</tr>
<tr class="odd">
<td><strong>C</strong></td>
<td>0.02</td>
<td>0.08</td>
<td>1.00</td>
</tr>
</tbody>
</table>
<p>The diagonal (self-relatedness) is close to 1; off-diagonal entries reflect how much genome-wide genetic material each pair shares. The core logic is the same intuition as HE regression: if genetics influences the trait, individuals who are more genetically similar (higher GRM entries) should be more phenotypically similar too — GREML just estimates this via restricted maximum likelihood rather than OLS, over a full genome-wide GRM rather than a handful of relatedness categories.</p>
</section>
<section id="why-greml-matters" class="level2" data-number="3.3">
<h2 data-number="3.3" class="anchored" data-anchor-id="why-greml-matters"><span class="header-section-number">3.3</span> Why GREML Matters</h2>
<p>GREML/GCTA was one of the methods that first demonstrated <strong>“missing heritability”</strong> could be recovered using genome-wide SNP data on unrelated individuals — showing that much of the heritability twin studies had estimated really was captured by common SNPs, just not by the small number of genome-wide-significant hits any single GWAS had found. This distinction between “heritability captured by genome-wide-significant SNPs” and “heritability captured by all measured SNPs” (the latter usually much larger) remains one of the central themes of statistical genetics.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>GREML uses a genome-wide Genetic Relationship Matrix (GRM) in a random-effects mixed model, estimated via restricted maximum likelihood.</li>
<li>It targets the random-individual expected variance estimand: <img src="https://latex.codecogs.com/png.latex?h%5E2%20=%20%5Csigma_g%5E2/(%5Csigma_g%5E2+%5Csigma_e%5E2)">.</li>
<li>GREML requires individual-level genotype data, unlike the summary-statistics methods covered later in this tutorial.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-4-binary-traits-the-liability-threshold-model-and-pcgc" class="level1" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> Part 4 — Binary Traits: The Liability Threshold Model and PCGC</h1>
<p>Everything in Parts 2–3 assumed a continuous, normally-distributed phenotype. Most disease traits, though, are binary: case or control. This creates a real problem for naive heritability estimation.</p>
<section id="the-ascertainment-problem" class="level2" data-number="4.1">
<h2 data-number="4.1" class="anchored" data-anchor-id="the-ascertainment-problem"><span class="header-section-number">4.1</span> The Ascertainment Problem</h2>
<p>Case-control GWAS deliberately <strong>oversample cases</strong>. A disease might have a true population prevalence <img src="https://latex.codecogs.com/png.latex?K"> of 1%, but researchers typically recruit a sample that’s 50% cases — otherwise there wouldn’t be enough cases to have any statistical power at all.</p>
<p>If you plug 0/1 case-control status directly into HE regression, you get a heritability estimate on the <strong>observed scale</strong> (<img src="https://latex.codecogs.com/png.latex?h%5E2_%7Bobs%7D">). Because of the deliberate oversampling, this number is heavily biased and not biologically meaningful — it reflects your sampling design as much as the underlying genetics.</p>
</section>
<section id="the-liability-threshold-model" class="level2" data-number="4.2">
<h2 data-number="4.2" class="anchored" data-anchor-id="the-liability-threshold-model"><span class="header-section-number">4.2</span> The Liability Threshold Model</h2>
<p>The standard fix: assume the binary trait is driven by an unobserved, continuous, normally-distributed <strong>liability</strong>.</p>
<ul>
<li>Everyone has a liability score, whether or not they’re a case.</li>
<li>If your liability crosses a threshold <img src="https://latex.codecogs.com/png.latex?t">, you become a case (<img src="https://latex.codecogs.com/png.latex?y=1">).</li>
<li>The threshold <img src="https://latex.codecogs.com/png.latex?t"> is set by the population prevalence <img src="https://latex.codecogs.com/png.latex?K"> — rarer diseases have a higher threshold.</li>
</ul>
<p>The quantity we actually want isn’t the heritability of the observed 0/1 scale — it’s the heritability of the underlying continuous <strong>liability scale</strong>, <img src="https://latex.codecogs.com/png.latex?h%5E2_%7Bliability%7D">.</p>
</section>
<section id="pcgc-fixing-the-regression-directly" class="level2" data-number="4.3">
<h2 data-number="4.3" class="anchored" data-anchor-id="pcgc-fixing-the-regression-directly"><span class="header-section-number">4.3</span> PCGC: Fixing the Regression Directly</h2>
<p>Golan et al.&nbsp;(2014) developed <strong>PCGC</strong> (“Phenotype Correlation–Genotype Correlation”) to solve this within the HE cross-product framework directly, rather than computing <img src="https://latex.codecogs.com/png.latex?h%5E2_%7Bobs%7D"> and applying an after-the-fact correction (which turns out to be mathematically unreliable under severe ascertainment).</p>
<p>Let <img src="https://latex.codecogs.com/png.latex?z"> be the height of the standard normal density at the liability threshold <img src="https://latex.codecogs.com/png.latex?t">, <img src="https://latex.codecogs.com/png.latex?P"> the case proportion in the ascertained sample, and <img src="https://latex.codecogs.com/png.latex?K"> the true population prevalence. PCGC shows that the expected phenotypic covariance in an ascertained sample is:</p>
<p><img src="https://latex.codecogs.com/png.latex?E%5By_iy_j%5D%20%5Capprox%20%5Cfrac%7Bz%5E2%5C,P(1-P)%7D%7BK%5E2(1-K)%5E2%7D%5C,%5Cpi_%7Bi,j%7D%5C,%5Csigma%5E2_%7Bg,%5Ctext%7Bliability%7D%7D"></p>
<p>The fix is elegant: scale the observed cross-products <img src="https://latex.codecogs.com/png.latex?y_iy_j"> by this prevalence-derived constant <em>before</em> regressing on the GRM (<img src="https://latex.codecogs.com/png.latex?%5Cpi_%7Bi,j%7D">), exactly as in ordinary HE regression. The result is a clean, directly-interpretable estimate of liability-scale heritability.</p>
</section>
<section id="why-this-matters-in-practice" class="level2" data-number="4.4">
<h2 data-number="4.4" class="anchored" data-anchor-id="why-this-matters-in-practice"><span class="header-section-number">4.4</span> Why This Matters in Practice</h2>
<p>Comparing raw observed-scale <img src="https://latex.codecogs.com/png.latex?h%5E2"> estimates across two case-control studies of the same disease — say, one with 30% cases and one with 50% cases — is comparing apples to oranges, since the observed-scale number depends on the ascertainment ratio, not just the underlying biology. <strong>Always convert to the liability scale before comparing heritability estimates across binary-trait studies</strong>, especially ones with different sampling designs or disease prevalence assumptions.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Case-control ascertainment biases naive (observed-scale) heritability estimates for binary traits.</li>
<li>The liability threshold model reframes disease as an unobserved continuous trait crossing a threshold set by population prevalence.</li>
<li>PCGC folds the correction directly into the HE cross-product regression, using a prevalence-based scaling factor, rather than a flawed post-hoc transformation.</li>
<li>Liability-scale <img src="https://latex.codecogs.com/png.latex?h%5E2">, not observed-scale <img src="https://latex.codecogs.com/png.latex?h%5E2">, is the number that’s comparable across studies with different ascertainment.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-5-ld-score-regression-heritability-from-summary-statistics-alone" class="level1" data-number="5">
<h1 data-number="5"><span class="header-section-number">5</span> Part 5 — LD Score Regression: Heritability from Summary Statistics Alone</h1>
<p>Everything so far — HE regression, GREML, PCGC — requires <strong>individual-level genotype data</strong>: actual genotypes for actual people. But most large GWAS consortia only release <strong>summary statistics</strong>: one effect size, standard error, and p-value per SNP, with no individual-level data at all (for privacy and logistical reasons). <strong>LD Score Regression (LDSC)</strong>, introduced by Bulik-Sullivan, Finucane, and colleagues in 2015, estimates heritability from summary statistics alone — no individual genotypes required.</p>
<section id="the-intuition-ld-amplifies-detectable-association" class="level2" data-number="5.1">
<h2 data-number="5.1" class="anchored" data-anchor-id="the-intuition-ld-amplifies-detectable-association"><span class="header-section-number">5.1</span> The Intuition: LD Amplifies Detectable Association</h2>
<p>Recall that SNPs correlated with a causal variant through linkage disequilibrium pick up some of that variant’s association signal — this is the same LD logic that underlies GWAS itself and PRS construction. The LDSC insight extends this one step further:</p>
<blockquote class="blockquote">
<p>A SNP that tags (is correlated with) <em>more</em> of the genome should show a <em>larger</em> marginal association signal on average — simply because it’s more likely to be picking up signal from a nearby causal variant.</p>
</blockquote>
</section>
<section id="from-fishers-polygenic-model-to-an-estimating-equation" class="level2" data-number="5.2">
<h2 data-number="5.2" class="anchored" data-anchor-id="from-fishers-polygenic-model-to-an-estimating-equation"><span class="header-section-number">5.2</span> From Fisher’s Polygenic Model to an Estimating Equation</h2>
<p>Assume a polygenic model (Fisher, 1918): <img src="https://latex.codecogs.com/png.latex?y_i%20=%20%5Csum_j%20%5Cbeta_j%20X_%7Bij%7D%20+%20%5Cvarepsilon_i">, with <img src="https://latex.codecogs.com/png.latex?%5Cbeta_j%20%5Csim%20%5B0,%5C%20h%5E2/M%5D"> — effect sizes drawn with variance spread evenly across <img src="https://latex.codecogs.com/png.latex?M"> SNPs. From GWAS, we observe marginal effect estimates <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_j%20=%20%5Cfrac%7B1%7D%7BN%7D%5Csum_i%20X_%7Bij%7Dy_i">. Taking the expectation of <img src="https://latex.codecogs.com/png.latex?N%5Chat%5Cbeta_j%5E2"> and working through the algebra:</p>
<p><img src="https://latex.codecogs.com/png.latex?E%5B%5Cchi_j%5E2%5D%20=%20%5Cfrac%7BNh%5E2%7D%7BM%7D%5C,%5Cell_j%20+%20Na%20+%201"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?%5Cell_j%20=%20%5Csum_k%20r_%7Bj,k%7D%5E2"> is the <strong>LD score</strong> of SNP <img src="https://latex.codecogs.com/png.latex?j"> — the sum of its squared correlations with every other SNP in the reference panel. This is a simple linear regression: regress each SNP’s GWAS <img src="https://latex.codecogs.com/png.latex?%5Cchi%5E2"> statistic against its LD score.</p>
<ul>
<li><strong>Slope</strong> <img src="https://latex.codecogs.com/png.latex?%5Cpropto%20Nh%5E2/M"> → estimates SNP heritability <img src="https://latex.codecogs.com/png.latex?h%5E2">.</li>
<li><strong>Intercept</strong> <img src="https://latex.codecogs.com/png.latex?%5Cpropto%20Na%20+%201"> → captures confounding, including population stratification. This is exactly what LD score regression was originally designed to detect: true polygenic signal should scale with LD, but confounding inflation (like population stratification) inflates test statistics roughly uniformly <em>regardless</em> of LD — so it shows up in the intercept, not the slope.</li>
</ul>
<p><strong>Worked example from the original literature:</strong> a schizophrenia GWAS (Psychiatric Genomics Consortium) showed <img src="https://latex.codecogs.com/png.latex?%5Clambda_%7BGC%7D%20=%201.48"> (substantial genomic inflation) but an LDSC intercept of only 1.06 — meaning the overwhelming majority of that inflation was consistent with genuine polygenic architecture, not confounding. This kind of decomposition is one of LDSC’s most valuable practical contributions: separating “real polygenicity” from “something’s wrong with your GWAS.”</p>
</section>
<section id="a-simulated-illustration-1" class="level2" data-number="5.3">
<h2 data-number="5.3" class="anchored" data-anchor-id="a-simulated-illustration-1"><span class="header-section-number">5.3</span> A Simulated Illustration</h2>
<div id="086179a9" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T19:08:06.034862Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T19:08:05.911447Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T19:08:06.109889Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T19:08:06.107873Z&quot;}}" data-execution_count="2">
<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;"># Illustrative LDSC-style simulation</span></span>
<span id="cb3-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;">42</span>)</span>
<span id="cb3-3">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;">5000</span>          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of SNPs</span></span>
<span id="cb3-4">N <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;">50000</span>         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># GWAS sample size</span></span>
<span id="cb3-5">h2_true <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 class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true heritability</span></span>
<span id="cb3-6">a_true  <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.01</span>    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># confounding/stratification inflation</span></span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulate LD scores (in reality, computed from a reference panel like 1000 Genomes)</span></span>
<span id="cb3-9">ld_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;">rgamma</span>(M, <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;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb3-10"></span>
<span id="cb3-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulate chi-squared statistics under the LDSC expectation, plus noise</span></span>
<span id="cb3-12">expected_chisq <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> h2_true <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> ld_score <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> a_true <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="cb3-13">chisq_obs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rgamma</span>(M, <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;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rate =</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_chisq)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># noisy draws around expectation</span></span>
<span id="cb3-14"></span>
<span id="cb3-15">ldsc_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;">lm</span>(chisq_obs <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> ld_score)</span>
<span id="cb3-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(ldsc_fit)</span>
<span id="cb3-17"></span>
<span id="cb3-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Recovering h2 and the intercept from the fitted slope/intercept</span></span>
<span id="cb3-19">slope_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;">coef</span>(ldsc_fit)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ld_score"</span>]]</span>
<span id="cb3-20">intercept_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;">coef</span>(ldsc_fit)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(Intercept)"</span>]]</span>
<span id="cb3-21">h2_hat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> slope_hat <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> N</span>
<span id="cb3-22"></span>
<span id="cb3-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Estimated h2:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(h2_hat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Estimated intercept (stratification proxy):"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(intercept_hat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>
Call:
lm(formula = chisq_obs ~ ld_score)

Residuals:
   Min     1Q Median     3Q    Max 
-907.6 -318.0  -97.4  198.9 4064.4 

Coefficients:
            Estimate Std. Error t value Pr(&gt;|t|)    
(Intercept) 486.5597    11.0465   44.05   &lt;2e-16 ***
ld_score      3.4683     0.2255   15.38   &lt;2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 452.4 on 4998 degrees of freedom
Multiple R-squared:  0.04519,   Adjusted R-squared:  0.045 
F-statistic: 236.6 on 1 and 4998 DF,  p-value: &lt; 2.2e-16</code></pre>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Estimated h2: 0.347 
Estimated intercept (stratification proxy): 486.56 </code></pre>
</div>
</div>
<p>The point of this simulation isn’t the exact numbers — it’s the mechanic: <strong>regress <img src="https://latex.codecogs.com/png.latex?%5Cchi%5E2"> statistics on LD scores, and the slope (rescaled by <img src="https://latex.codecogs.com/png.latex?M/N">) is your heritability estimate.</strong></p>
</section>
<section id="the-duality-between-he-regression-and-ldsc" class="level2" data-number="5.4">
<h2 data-number="5.4" class="anchored" data-anchor-id="the-duality-between-he-regression-and-ldsc"><span class="header-section-number">5.4</span> The Duality Between HE Regression and LDSC</h2>
<p>These two methods are more closely related than they might look:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th></th>
<th>HE regression (sample space)</th>
<th>LDSC (marker space)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Matrix</td>
<td><img src="https://latex.codecogs.com/png.latex?XX%5ET"> → <img src="https://latex.codecogs.com/png.latex?N%5Ctimes%20N"> (GRM: relatedness between <em>people</em>)</td>
<td><img src="https://latex.codecogs.com/png.latex?X%5ETX"> → <img src="https://latex.codecogs.com/png.latex?M%5Ctimes%20M"> (LD matrix: correlation between <em>SNPs</em>)</td>
</tr>
<tr class="even">
<td>Regress</td>
<td>phenotype cross-products on the GRM</td>
<td>GWAS <img src="https://latex.codecogs.com/png.latex?%5Cchi%5E2"> statistics on LD scores</td>
</tr>
<tr class="odd">
<td>Underlying question</td>
<td>Do genetically-similar people have similar phenotypes?</td>
<td>Do SNPs that tag more of the genome show bigger effects?</td>
</tr>
</tbody>
</table>
<p>By the rules of linear algebra, these two spaces contain the same total information about genetic variance — they’re dual views of the same underlying question. But summarizing the full <img src="https://latex.codecogs.com/png.latex?M%5Ctimes%20M"> LD matrix down to one number per SNP (<img src="https://latex.codecogs.com/png.latex?%5Cell_j">) throws away the specific <em>shape</em> of how SNPs correlate with each other — information the full GRM in HE regression preserves. <strong>This is exactly why HE regression, using individual-level data, is statistically more powerful than LDSC using summary statistics alone.</strong> LDSC trades some statistical power for the enormous practical advantage of not needing individual-level genotypes.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>LDSC estimates heritability from GWAS summary statistics alone, by regressing each SNP’s <img src="https://latex.codecogs.com/png.latex?%5Cchi%5E2"> statistic on its LD score.</li>
<li>The slope of this regression estimates heritability; the intercept estimates confounding/stratification inflation — letting you decompose genomic inflation into “real polygenicity” vs.&nbsp;“something’s wrong.”</li>
<li>LDSC and HE regression are dual views of the same underlying variance information — marker-space vs.&nbsp;sample-space — with HE regression retaining more statistical power at the cost of requiring individual-level data.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-6-relaxing-ldscs-assumptions" class="level1" data-number="6">
<h1 data-number="6"><span class="header-section-number">6</span> Part 6 — Relaxing LDSC’s Assumptions</h1>
<p>Standard LDSC is a <strong>method-of-moments</strong> estimator — it needs only <img src="https://latex.codecogs.com/png.latex?E%5B%5Cbeta_j%5D=0"> and <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(%5Cbeta_j)=%5Csigma_g%5E2/M">, with no strict distributional (Gaussian) assumption on effect sizes. But it does assume something stronger than it first appears: a <strong>uniform genetic architecture</strong>, where every SNP is expected to explain exactly the same amount of phenotypic variance, regardless of its LD, minor allele frequency, or biological function.</p>
<section id="where-the-uniformity-assumption-actually-hides" class="level2" data-number="6.1">
<h2 data-number="6.1" class="anchored" data-anchor-id="where-the-uniformity-assumption-actually-hides"><span class="header-section-number">6.1</span> Where the Uniformity Assumption Actually Hides</h2>
<p>It’s not just the <img src="https://latex.codecogs.com/png.latex?%5Csigma_g%5E2/M"> term — it’s baked into how the genotype matrix <img src="https://latex.codecogs.com/png.latex?X"> is defined. LDSC standardizes genotypes:</p>
<p><img src="https://latex.codecogs.com/png.latex?X_%7Bi,j%7D%20=%20%5Cfrac%7Bg_%7Bi,j%7D%20-%202p_j%7D%7B%5Csqrt%7B2p_j(1-p_j)%7D%7D"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?g_%7Bi,j%7D"> is the raw allele count and <img src="https://latex.codecogs.com/png.latex?p_j"> is the minor allele frequency. Standardizing forces every SNP’s column to have variance exactly 1, so <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(X_j%5Cbeta_j)%20=%20%5Csigma_g%5E2/M"> for <em>every</em> SNP regardless of its frequency. The consequence: dividing by <img src="https://latex.codecogs.com/png.latex?%5Csqrt%7B2p_j(1-p_j)%7D"> inflates the allelic-scale effect-size variance of rare variants specifically.</p>
<p>This wasn’t an oversight — the LDSC authors were fully aware of it, and chose it deliberately for two reasons: (1) it makes <img src="https://latex.codecogs.com/png.latex?X%5ETX"> a clean correlation matrix, simplifying the algebra considerably; (2) it’s empirically defensible, since effect-size variance genuinely does tend to increase as allele frequency decreases, consistent with negative selection acting more strongly against common large-effect variants.</p>
</section>
<section id="relaxing-the-frequency-assumption-the-α-parameter" class="level2" data-number="6.2">
<h2 data-number="6.2" class="anchored" data-anchor-id="relaxing-the-frequency-assumption-the-α-parameter"><span class="header-section-number">6.2</span> Relaxing the Frequency Assumption: The α Parameter</h2>
<p>Is the standard uniformity assumption the right fit for every trait? Not necessarily. We can generalize it with a parameter <img src="https://latex.codecogs.com/png.latex?%5Calpha">:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(%5Cbeta_j)%20%5Cpropto%20%5Bp_j(1-p_j)%5D%5E%7B1+%5Calpha%7D"></p>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>α</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><img src="https://latex.codecogs.com/png.latex?-1"> (LDSC default)</td>
<td>Variance independent of MAF — common and rare variants explain equal expected variance</td>
</tr>
<tr class="even">
<td><img src="https://latex.codecogs.com/png.latex?0"></td>
<td>Effect size (not variance) independent of MAF — common variants explain more overall variance</td>
</tr>
<tr class="odd">
<td><img src="https://latex.codecogs.com/png.latex?%3C%20-1"></td>
<td>Strong negative selection — rare variants dominate the variance</td>
</tr>
</tbody>
</table>
<p>Introducing <img src="https://latex.codecogs.com/png.latex?%5Calpha"> changes the LD score itself into a weighted version, <img src="https://latex.codecogs.com/png.latex?%5Cell_j(%5Calpha)%20=%20%5Csum_k%20r_%7Bj,k%7D%5E2%5C,%5Bp_k(1-p_k)%5D%5E%7B1+%5Calpha%7D">, which then plugs into the same regression machinery as before.</p>
<p><strong>How is α estimated?</strong> Via profile likelihood: define a grid of candidate <img src="https://latex.codecogs.com/png.latex?%5Calpha"> values, compute the expected GWAS <img src="https://latex.codecogs.com/png.latex?%5Cchi%5E2"> statistics under each, compare to the actual observed statistics, and pick the <img src="https://latex.codecogs.com/png.latex?%5Calpha"> that maximizes model likelihood. Empirically, across many complex traits the true <img src="https://latex.codecogs.com/png.latex?%5Calpha"> tends to fall between <img src="https://latex.codecogs.com/png.latex?-0.25"> and <img src="https://latex.codecogs.com/png.latex?-0.5"> — suggesting the default <img src="https://latex.codecogs.com/png.latex?%5Calpha=-1"> may somewhat overestimate the contribution of rare variants for many traits.</p>
</section>
<section id="relaxing-the-ld-assumption-ldak-and-sumher" class="level2" data-number="6.3">
<h2 data-number="6.3" class="anchored" data-anchor-id="relaxing-the-ld-assumption-ldak-and-sumher"><span class="header-section-number">6.3</span> Relaxing the LD Assumption: LDAK and SumHer</h2>
<p>A different critique: if ten SNPs sit in near-perfect LD, they likely all tag the same underlying causal variant — but standard LDSC gives each of them full weight, effectively inflating that region’s apparent contribution. <strong>LDAK</strong> (Speed &amp; Balding) introduces an LD-based weight <img src="https://latex.codecogs.com/png.latex?w_j"> per SNP — SNPs in dense LD regions get <em>down-weighted</em>, SNPs in low-LD regions (more independent signal) get <em>up-weighted</em>: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(%5Cbeta_j)%20%5Cpropto%20w_j">.</p>
</section>
<section id="relaxing-the-functional-assumption-stratified-ldsc-s-ldsc" class="level2" data-number="6.4">
<h2 data-number="6.4" class="anchored" data-anchor-id="relaxing-the-functional-assumption-stratified-ldsc-s-ldsc"><span class="header-section-number">6.4</span> Relaxing the Functional Assumption: Stratified LDSC (s-LDSC)</h2>
<p>A third critique: a SNP sitting inside an active promoter or coding region is plausibly more likely to be causal than one in an intergenic “desert” — biology isn’t uniform across the genome. <strong>Stratified LD Score Regression</strong> (Finucane et al., 2015) partitions the variance across <img src="https://latex.codecogs.com/png.latex?C"> overlapping functional annotation categories instead of assuming one genome-wide <img src="https://latex.codecogs.com/png.latex?%5Csigma_g%5E2">:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(%5Cbeta_j)%20=%20%5Csum_%7Bc=1%7D%5E%7BC%7D%20a_%7Bjc%7D%5C,%5Ctau_c"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?a_%7Bjc%7D=1"> if SNP <img src="https://latex.codecogs.com/png.latex?j"> belongs to annotation category <img src="https://latex.codecogs.com/png.latex?c"> (0 otherwise), and <img src="https://latex.codecogs.com/png.latex?%5Ctau_c"> is the per-SNP heritability contribution of category <img src="https://latex.codecogs.com/png.latex?c">. The regression itself generalizes to a multiple regression: <img src="https://latex.codecogs.com/png.latex?E%5BN%5Chat%5Cbeta_j%5E2%5D%20=%20N%5Csum_C%20%5Ctau_C%5C,%5Cell(j,C)%20+%20Na%20+%201">, where <img src="https://latex.codecogs.com/png.latex?%5Cell(j,C)%20=%20%5Csum_%7Bk%5Cin%20C%7D%20r_%7Bj,k%7D%5E2"> measures how much of category <img src="https://latex.codecogs.com/png.latex?C"> is tagged by SNP <img src="https://latex.codecogs.com/png.latex?j">.</p>
<p>The widely-used <strong>“baseline model”</strong> is simply a specific choice of about 24 core functional annotations (plus flanking windows around them) used as the default category set.</p>
<p><strong>What can you do with this?</strong> Two useful quantities fall out directly: the heritability of category <img src="https://latex.codecogs.com/png.latex?C"> itself, <img src="https://latex.codecogs.com/png.latex?h%5E2(C)%20=%20%5Csum_%7Bj%5Cin%20C%7D%5Cbeta_j%5E2">, and whether category <img src="https://latex.codecogs.com/png.latex?C"> is “punching above its weight” — comparing <img src="https://latex.codecogs.com/png.latex?h%5E2(C)/h%5E2"> to <img src="https://latex.codecogs.com/png.latex?%7CC%7C"> (the category’s share of the genome). If a category explains disproportionately more heritability than its size would predict, that’s <strong>heritability enrichment</strong> — a signal that the category is biologically important, and a concept that carries forward directly into methods like SBayesRC (Part 8).</p>
</section>
<section id="all-four-approaches-side-by-side" class="level2" data-number="6.5">
<h2 data-number="6.5" class="anchored" data-anchor-id="all-four-approaches-side-by-side"><span class="header-section-number">6.5</span> All Four Approaches, Side by Side</h2>
<p>Every method below is really the same method-of-moments regression machinery, applied under a different assumption about <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(%5Cbeta_j)">:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Variance assumption</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Standard LDSC</td>
<td>Uniform: <img src="https://latex.codecogs.com/png.latex?%5Csigma_g%5E2/M"></td>
</tr>
<tr class="even">
<td>SumHer / LDAK</td>
<td>Scaled by LD weights <img src="https://latex.codecogs.com/png.latex?w_j"> (and optionally MAF via α)</td>
</tr>
<tr class="odd">
<td>α-modeled LDSC</td>
<td>Scaled by MAF: <img src="https://latex.codecogs.com/png.latex?%5Bp_j(1-p_j)%5D%5E%7B1+%5Calpha%7D"></td>
</tr>
<tr class="even">
<td>s-LDSC</td>
<td>Sum of functional-annotation contributions: <img src="https://latex.codecogs.com/png.latex?%5Csum_c%20a_%7Bjc%7D%5Ctau_c"></td>
</tr>
</tbody>
</table>
<p>The statistical framework stays fixed; what changes is the biological model of genetic architecture baked into the variance assumption.</p>
</section>
<section id="a-brief-aside-non-additive-dominance-heritability" class="level2" data-number="6.6">
<h2 data-number="6.6" class="anchored" data-anchor-id="a-brief-aside-non-additive-dominance-heritability"><span class="header-section-number">6.6</span> A Brief Aside: Non-Additive (Dominance) Heritability</h2>
<p>Everything so far assumes purely additive genetic effects. <strong>Dominance variance</strong> (<img src="https://latex.codecogs.com/png.latex?%5Csigma_d%5E2">) captures whether the heterozygote genotype deviates from the exact midpoint of the two homozygotes. Modeling this requires an orthogonal encoding of additive and dominance genotype codes (achievable under Hardy-Weinberg equilibrium), which then permits two independent LD score regressions — one additive, one dominance — since dominance LD decays at the <em>square</em> of additive LD (much faster with physical distance).</p>
<p>Applied across roughly 1,100 traits in UK Biobank, dominance heritability turned out to be small — typically under 5% of total genetic variance, and often statistically indistinguishable from zero. This doesn’t mean dominance never matters biologically at individual loci — but at the population-variance level, additive effects absorb most of what a two-degree-of-freedom model can explain. <strong>The standard additive-only GWAS assumption holds up well for most complex traits.</strong></p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Standard LDSC’s “uniform architecture” assumption is baked into genotype standardization, and can be relaxed in several directions.</li>
<li>The α parameter relaxes the MAF assumption; LDAK/SumHer relax the LD-density assumption; stratified LDSC (s-LDSC) relaxes the functional/annotation assumption.</li>
<li>All of these remain method-of-moments regressions — only the assumed variance structure of SNP effects changes.</li>
<li>Non-additive (dominance) heritability is generally small for complex traits, validating the standard additive GWAS model.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-7-genetic-correlation-do-two-traits-share-genetic-architecture" class="level1" data-number="7">
<h1 data-number="7"><span class="header-section-number">7</span> Part 7 — Genetic Correlation: Do Two Traits Share Genetic Architecture?</h1>
<p>Everything so far has focused on a single trait. But one of the most common questions in statistical genetics involves <em>two</em> traits: do depression and obesity share genetic causes? Are psychiatric disorders genetically related to each other? Does elevated cholesterol share genetic architecture with heart disease? Answering these requires <strong>genetic correlation</strong>.</p>
<section id="motivation" class="level2" data-number="7.1">
<h2 data-number="7.1" class="anchored" data-anchor-id="motivation"><span class="header-section-number">7.1</span> Motivation</h2>
<p>The goal is to determine the shared genetics of two traits — schematically, whether the genetic effects underlying Trait A and Trait B overlap. This matters for two main reasons: uncovering <strong>causal pathways</strong> (e.g.&nbsp;cholesterol → heart disease) and informing <strong>categorization</strong> of related conditions (e.g.&nbsp;clustering psychiatric disorders by shared genetic architecture rather than by symptom overlap alone).</p>
</section>
<section id="four-reasons-two-traits-can-be-genetically-correlated" class="level2" data-number="7.2">
<h2 data-number="7.2" class="anchored" data-anchor-id="four-reasons-two-traits-can-be-genetically-correlated"><span class="header-section-number">7.2</span> Four Reasons Two Traits Can Be Genetically Correlated</h2>
<p>A single variant or gene influencing multiple traits is called <strong>pleiotropy</strong>, and it comes in several distinct flavors — each with a different biological and causal interpretation:</p>
<p><strong>Vertical pleiotropy</strong> (<img src="https://latex.codecogs.com/png.latex?G%20%5Cto%20x%20%5Cto%20y">): the variant affects trait <img src="https://latex.codecogs.com/png.latex?x">, which in turn causally affects trait <img src="https://latex.codecogs.com/png.latex?y">. The genetic correlation here reflects a genuine causal chain.</p>
<p><strong>Horizontal pleiotropy</strong> (<img src="https://latex.codecogs.com/png.latex?G%20%5Cto%20x"> and <img src="https://latex.codecogs.com/png.latex?G%20%5Cto%20y">, independently): the same variant affects both traits through separate biological pathways, with no causal link between <img src="https://latex.codecogs.com/png.latex?x"> and <img src="https://latex.codecogs.com/png.latex?y"> themselves.</p>
<p><strong>Pleiotropy via an intermediate phenotype</strong> (<img src="https://latex.codecogs.com/png.latex?G%20%5Cto%20z%20%5Cto%20x"> and <img src="https://latex.codecogs.com/png.latex?z%20%5Cto%20y">): an “endophenotype” <img src="https://latex.codecogs.com/png.latex?z"> mediates the shared effect — for example, latent factors underlying clusters of psychiatric disorders (Grotzinger et al., 2025).</p>
<p><strong>Spurious pleiotropy (via LD)</strong>: two distinct causal variants, <img src="https://latex.codecogs.com/png.latex?G_1%20%5Cto%20x"> and <img src="https://latex.codecogs.com/png.latex?G_2%20%5Cto%20y">, happen to sit in LD with each other (or with a shared marker). This <em>looks</em> like pleiotropy in the data but reflects two independent causal mechanisms that are simply co-inherited — an artifact of genome structure, not shared biology.</p>
<blockquote class="blockquote">
<p><strong>Mendelian Randomization can distinguish vertical from horizontal pleiotropy</strong> — this is exactly the tool genetic correlation itself cannot provide, since <img src="https://latex.codecogs.com/png.latex?r_g"> only tells you <em>whether</em> shared genetic architecture exists, not its direction or mechanism.</p>
</blockquote>
</section>
<section id="from-variancecovariancecorrelation-to-heritabilitygenetic-covariancegenetic-correlation" class="level2" data-number="7.3">
<h2 data-number="7.3" class="anchored" data-anchor-id="from-variancecovariancecorrelation-to-heritabilitygenetic-covariancegenetic-correlation"><span class="header-section-number">7.3</span> From Variance/Covariance/Correlation to Heritability/Genetic Covariance/Genetic Correlation</h2>
<p>The mathematical structure of genetic correlation is a direct analogy to ordinary variance and covariance:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(X)%20=%20%5Ctext%7BCov%7D(X,X),%20%5Cqquad%20%5Ctext%7BCorr%7D(X,Y)%20=%20%5Cfrac%7B%5Ctext%7BCov%7D(X,Y)%7D%7B%5Csigma_x%5Csigma_y%7D"></p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>General statistical concept</th>
<th>Genetics equivalent</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(X)"></td>
<td><img src="https://latex.codecogs.com/png.latex?h%5E2"> — heritability</td>
</tr>
<tr class="even">
<td><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BCov%7D(X,Y)"></td>
<td><img src="https://latex.codecogs.com/png.latex?%5Crho_g"> — genetic covariance</td>
</tr>
<tr class="odd">
<td><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BCorr%7D(X,Y)"></td>
<td><img src="https://latex.codecogs.com/png.latex?r_g"> — genetic correlation</td>
</tr>
</tbody>
</table>
<p>So the whole problem of estimating genetic correlation reduces to estimating heritability (variance) and genetic covariance (covariance) — as the saying goes, all you really need is covariance.</p>
</section>
<section id="cross-trait-ld-score-regression" class="level2" data-number="7.4">
<h2 data-number="7.4" class="anchored" data-anchor-id="cross-trait-ld-score-regression"><span class="header-section-number">7.4</span> Cross-Trait LD Score Regression</h2>
<p>Cross-trait LDSC extends the single-trait <img src="https://latex.codecogs.com/png.latex?%5Cchi%5E2">-on-LD-score regression from Part 5 to a <strong>product of Z-scores</strong> across two GWAS:</p>
<p><img src="https://latex.codecogs.com/png.latex?E%5Bz_%7B1j%7Dz_%7B2j%7D%5D%20=%20%5Cfrac%7B%5Csqrt%7BN_1N_2%7D%5C,%5Crho_g%7D%7BM%7D%5C,%5Cell_j%20+%20%5Cfrac%7B%5Crho%5C,N_s%7D%7B%5Csqrt%7BN_1N_2%7D%7D"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?z_%7B1j%7D,%20z_%7B2j%7D"> are Z-scores for the two traits at SNP <img src="https://latex.codecogs.com/png.latex?j">; <img src="https://latex.codecogs.com/png.latex?N_1,%20N_2"> are the two GWAS sample sizes; <img src="https://latex.codecogs.com/png.latex?%5Crho_g"> is genetic covariance; <img src="https://latex.codecogs.com/png.latex?M"> is the number of reference SNPs; <img src="https://latex.codecogs.com/png.latex?%5Cell_j"> is the LD score; <img src="https://latex.codecogs.com/png.latex?%5Crho"> is the phenotypic correlation between the traits; and <img src="https://latex.codecogs.com/png.latex?N_s"> is the number of individuals overlapping between the two studies.</p>
<p>The <strong>slope</strong> of this regression estimates genetic covariance <img src="https://latex.codecogs.com/png.latex?%5Crho_g"> (which is then rescaled into the correlation <img src="https://latex.codecogs.com/png.latex?r_g">); the <strong>intercept</strong> absorbs any phenotypic correlation induced by sample overlap between the two GWAS.</p>
<p><strong>Single-trait LDSC is a special case of this equation.</strong> Set trait 1 = trait 2 (so <img src="https://latex.codecogs.com/png.latex?N_1=N_2=N">, <img src="https://latex.codecogs.com/png.latex?%5Crho=1">, complete overlap), and the cross-trait equation reduces exactly to the standard single-trait form from Part 5, <img src="https://latex.codecogs.com/png.latex?E%5B%5Cchi_j%5E2%5D%20=%20%5Cfrac%7BNh%5E2%7D%7BM%7D%5Cell_j%20+%201">. Genetic correlation and heritability estimation are, mathematically, the same regression viewed from two different angles.</p>
<p><strong>Robustness to sample overlap.</strong> A reassuring property: cross-trait LDSC remains fairly robust even when the two GWAS share participants (<img src="https://latex.codecogs.com/png.latex?N_s%20%3E%200">). Overlap tends to inflate the <em>intercept</em> roughly uniformly across variants, rather than biasing the <em>slope</em> — meaning the <img src="https://latex.codecogs.com/png.latex?r_g"> estimate itself stays comparatively reliable even in the presence of sample overlap, unlike many other cross-trait methods.</p>
</section>
<section id="a-simulated-illustration-2" class="level2" data-number="7.5">
<h2 data-number="7.5" class="anchored" data-anchor-id="a-simulated-illustration-2"><span class="header-section-number">7.5</span> A Simulated Illustration</h2>
<div id="5f19c6eb" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T19:08:06.114574Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T19:08:06.112867Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T19:08:06.177065Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T19:08:06.175026Z&quot;}}" data-execution_count="3">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Illustrative cross-trait LDSC simulation</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;">7</span>)</span>
<span id="cb6-3">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;">5000</span></span>
<span id="cb6-4">N1 <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;">40000</span>; N2 <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;">40000</span></span>
<span id="cb6-5">rho_g_true <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 class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true genetic covariance</span></span>
<span id="cb6-6">rho_true   <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.0</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># phenotypic correlation from any sample overlap</span></span>
<span id="cb6-7">Ns_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;">0</span>      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># no overlapping samples in this illustration</span></span>
<span id="cb6-8"></span>
<span id="cb6-9">ld_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;">rgamma</span>(M, <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;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb6-10"></span>
<span id="cb6-11">expected_z1z2 <span class="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> rho_g_true <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> ld_score <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-12">                 (rho_true <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> Ns_true) <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>(N1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> N2)</span>
<span id="cb6-13"></span>
<span id="cb6-14">z1z2_obs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> expected_z1z2 <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;">rnorm</span>(M, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</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;"># add regression noise</span></span>
<span id="cb6-15"></span>
<span id="cb6-16">cross_ldsc_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;">lm</span>(z1z2_obs <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> ld_score)</span>
<span id="cb6-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(cross_ldsc_fit)</span>
<span id="cb6-18"></span>
<span id="cb6-19">rho_g_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;">coef</span>(cross_ldsc_fit)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ld_score"</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;">sqrt</span>(N1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> N2)</span>
<span id="cb6-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Estimated genetic covariance:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(rho_g_hat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>
Call:
lm(formula = z1z2_obs ~ ld_score)

Residuals:
    Min      1Q  Median      3Q     Max 
-6.4236 -1.3460 -0.0022  1.3030  6.7866 

Coefficients:
            Estimate Std. Error  t value Pr(&gt;|t|)    
(Intercept) 0.052421   0.049026    1.069    0.285    
ld_score    2.398684   0.001003 2391.175   &lt;2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.984 on 4998 degrees of freedom
Multiple R-squared:  0.9991,    Adjusted R-squared:  0.9991 
F-statistic: 5.718e+06 on 1 and 4998 DF,  p-value: &lt; 2.2e-16</code></pre>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Estimated genetic covariance: 0.3 </code></pre>
</div>
</div>
<p>Exactly as with single-trait LDSC, the mechanic is what matters: <strong>regress the product of Z-scores across two traits on LD score, and the slope gives genetic covariance.</strong></p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Genetic correlation asks whether two traits share genetic architecture — quantified as <img src="https://latex.codecogs.com/png.latex?r_g">, the correlation of their genetic components.</li>
<li>Pleiotropy underlying genetic correlation comes in several distinct flavors: vertical, horizontal, mediated by an intermediate phenotype, or spurious (via LD) — each implies a different biological story.</li>
<li>Cross-trait LDSC extends single-trait LDSC to a product-of-Z-scores regression; single-trait LDSC is the special case where a trait is compared against itself.</li>
<li>Genetic correlation, unlike Mendelian Randomization, cannot on its own distinguish <em>why</em> two traits are correlated — only <em>whether</em> they are.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-8-interpreting-genetic-correlation-and-its-limitations" class="level1" data-number="8">
<h1 data-number="8"><span class="header-section-number">8</span> Part 8 — Interpreting Genetic Correlation, and Its Limitations</h1>
<p>Having a formula for <img src="https://latex.codecogs.com/png.latex?r_g"> is only half the job — interpreting it correctly, and knowing when to distrust it, matters just as much.</p>
<section id="reading-the-sign-and-magnitude" class="level2" data-number="8.1">
<h2 data-number="8.1" class="anchored" data-anchor-id="reading-the-sign-and-magnitude"><span class="header-section-number">8.1</span> Reading the Sign and Magnitude</h2>
<p><img src="https://latex.codecogs.com/png.latex?r_g"> ranges conceptually from <img src="https://latex.codecogs.com/png.latex?-1"> to <img src="https://latex.codecogs.com/png.latex?+1">:</p>
<ul>
<li><strong>Positive</strong> <img src="https://latex.codecogs.com/png.latex?r_g">: genetic effects on the two traits point in the same direction.</li>
<li><strong>Negative</strong> <img src="https://latex.codecogs.com/png.latex?r_g">: genetic effects point in opposite directions.</li>
<li><strong>Zero</strong> <img src="https://latex.codecogs.com/png.latex?r_g">: either the genetic effects are essentially uncorrelated genome-wide, <em>or</em> positive and negative local genetic correlations are canceling out across the genome. This second possibility is worth remembering — a genome-wide <img src="https://latex.codecogs.com/png.latex?r_g"> near zero doesn’t rule out strong correlation concentrated in specific regions (this is what dedicated <em>local</em> genetic correlation methods, like LAVA or SUPERGNOVA, are built to detect).</li>
</ul>
<p><strong>Real examples from the literature</strong> (Bulik-Sullivan, Finucane et al., 2015): positive genetic correlations cluster among metabolic disorders, lipid/heart-disease traits, growth-related traits, and psychiatric disorders; negative correlations appear between HDL cholesterol and other metabolic/cardiovascular traits, and between years of education and risk factors like smoking, BMI, and LDL cholesterol.</p>
<p>One more practical note: cross-trait LDSC generally has <strong>wider standard errors</strong> than either individual-level methods or single-trait LDSC’s own heritability estimates — a noisy-looking <img src="https://latex.codecogs.com/png.latex?r_g"> estimate isn’t necessarily a red flag on its own, it may just reflect the inherently lower precision of the cross-trait regression.</p>
</section>
<section id="four-limitations-to-keep-in-mind" class="level2" data-number="8.2">
<h2 data-number="8.2" class="anchored" data-anchor-id="four-limitations-to-keep-in-mind"><span class="header-section-number">8.2</span> Four Limitations to Keep in Mind</h2>
<p><strong>1. Traits must be sufficiently heritable.</strong> If a trait’s own heritability is too low, the genetic correlation regression can mechanically produce <img src="https://latex.codecogs.com/png.latex?%7Cr_g%7C%20%3E%201"> — a nonsensical value that nonetheless falls directly out of the math when the underlying signal-to-noise ratio is too poor. As a practical rule of thumb, treat <img src="https://latex.codecogs.com/png.latex?%5Crho_g"> estimates involving any trait whose heritability Z-score is below 4 as too noisy to trust.</p>
<p><strong>2. The method assumes polygenicity.</strong> LDSC-based genetic correlation works best for traits with many small-effect causal variants spread across the genome. It’s less reliable for traits dominated by a handful of large-effect loci, since the underlying regression logic depends on polygenic averaging across many SNPs.</p>
<p><strong>3. Reverse causation can masquerade as genetic correlation.</strong> A positive genetic correlation between obesity and depression, for instance, is equally consistent with obesity causally influencing depression risk, or depression causally influencing obesity risk (Speed et al., 2019). Genetic correlation is symmetric and directionless by construction — it cannot tell you which way, if either, causality runs. That question requires Mendelian Randomization, not <img src="https://latex.codecogs.com/png.latex?r_g">.</p>
<p><strong>4. Assortative mating can inflate estimates.</strong> If people non-randomly choose partners who resemble them on a given trait (assortative mating, with correlation <img src="https://latex.codecogs.com/png.latex?%5Crho_m%20%3E%200"> between mates), the equilibrium genetic correlation exceeds the “true” underlying genetic correlation: <img src="https://latex.codecogs.com/png.latex?%5Crho_%7Bg,%5Ctext%7Beq%7D%7D%20%3E%20%5Crho_g"> whenever <img src="https://latex.codecogs.com/png.latex?%5Crho_m%20%3E%200"> (and <img src="https://latex.codecogs.com/png.latex?%5Crho_%7Bg,%5Ctext%7Beq%7D%7D%20=%20%5Crho_g"> only when there’s no assortative mating, <img src="https://latex.codecogs.com/png.latex?%5Crho_m%20=%200">). This is a subtle confound worth remembering specifically for traits known to be assortatively mated on — height and educational attainment are classic examples.</p>
</section>
<section id="extension-genomic-sem" class="level2" data-number="8.3">
<h2 data-number="8.3" class="anchored" data-anchor-id="extension-genomic-sem"><span class="header-section-number">8.3</span> Extension: Genomic SEM</h2>
<p>Once you can estimate genetic correlations pairwise between many traits, a natural next step is to model the <em>structure</em> of that correlation across all of them simultaneously. <strong>Genomic SEM</strong> (Grotzinger et al., 2019) is exactly this — a two-step framework:</p>
<ol type="1">
<li>Estimate the full genetic covariance matrix <img src="https://latex.codecogs.com/png.latex?S"> across many traits, using pairwise cross-trait LDSC.</li>
<li>Decompose that covariance matrix into latent genetic factors — structural equation modeling (see our companion SEM tutorial) applied to a <em>genetic</em> covariance matrix, rather than a raw phenotypic one.</li>
</ol>
<p>This is precisely how researchers have identified shared latent genetic factors underlying clusters of psychiatric disorders (Grotzinger et al., 2025) — the same <code>factor =~ indicator</code> measurement-model logic from classical SEM, just with the genetic covariance matrix standing in for the raw phenotypic covariance matrix.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Interpret <img src="https://latex.codecogs.com/png.latex?r_g">’s sign as the direction of shared genetic effects, but remember a near-zero genome-wide estimate can still mask strong local correlation.</li>
<li>Genetic correlation requires reasonably heritable, polygenic traits to be reliable, and is symmetric — it cannot establish which trait causes the other (that’s Mendelian Randomization’s job).</li>
<li>Assortative mating is a distinct, easy-to-overlook confound that can inflate <img src="https://latex.codecogs.com/png.latex?r_g"> estimates above their “true” value.</li>
<li>Genomic SEM extends pairwise genetic correlation into a full structural model across many traits at once, using the same measurement-model logic as ordinary SEM.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-9-practical-checklist-and-where-this-leads-next" class="level1" data-number="9">
<h1 data-number="9"><span class="header-section-number">9</span> Part 9 — Practical Checklist, and Where This Leads Next</h1>
<section id="before-you-trust-an-ldsc-heritability-or-genetic-correlation-estimate" class="level2" data-number="9.1">
<h2 data-number="9.1" class="anchored" data-anchor-id="before-you-trust-an-ldsc-heritability-or-genetic-correlation-estimate"><span class="header-section-number">9.1</span> Before You Trust an LDSC Heritability or Genetic Correlation Estimate</h2>
<p>A short, practical checklist worth running through before reporting or relying on any LDSC-based result:</p>
<ul>
<li><strong>Ancestry-matched LD reference.</strong> LD scores must come from a reference panel matching the GWAS population’s genetic ancestry — the same ancestry-matching concern that recurs throughout fine-mapping and PRS.</li>
<li><strong>Sufficient sample size.</strong> LDSC gets noisy at low <img src="https://latex.codecogs.com/png.latex?N"> — a common rule of thumb is <img src="https://latex.codecogs.com/png.latex?N%20%3E%203%7B,%7D000"> for standard LDSC and <img src="https://latex.codecogs.com/png.latex?N%20%3E%205%7B,%7D000"> for stratified LDSC.</li>
<li><strong>Sufficient polygenicity.</strong> The method works poorly if very few SNPs actually affect the trait; watch out for a small number of unusually large-effect variants distorting the regression.</li>
<li><strong>Liability-scale conversion for binary traits.</strong> Never compare raw observed-scale <img src="https://latex.codecogs.com/png.latex?h%5E2"> estimates across studies with different case-control ascertainment — convert to the liability scale first (Part 4).</li>
<li><strong>Custom annotations in s-LDSC</strong> need to actually work correctly under block-jackknife resampling if you’re building your own annotation categories.</li>
<li><strong>Genomic control caution.</strong> If genomic control has already been applied to input summary statistics, <img src="https://latex.codecogs.com/png.latex?h%5E2"> estimates can be distorted — but <img src="https://latex.codecogs.com/png.latex?r_g"> estimates are comparatively robust to this.</li>
<li><strong>Low-heritability trait pairs.</strong> Treat <img src="https://latex.codecogs.com/png.latex?%5Crho_g">/<img src="https://latex.codecogs.com/png.latex?r_g"> estimates involving any trait with an <img src="https://latex.codecogs.com/png.latex?h%5E2"> Z-score below 4 as too noisy to trust, regardless of how the point estimate looks.</li>
</ul>
</section>
<section id="the-common-thread" class="level2" data-number="9.2">
<h2 data-number="9.2" class="anchored" data-anchor-id="the-common-thread"><span class="header-section-number">9.2</span> The Common Thread</h2>
<p>Looking back across this whole tutorial, there’s really one continuous story: <strong>relaxing the assumption that every SNP matters equally.</strong></p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BHE%20regression%7D%20%5Crightarrow%20%5Ctext%7BGREML%7D%20%5Crightarrow%20%5Ctext%7BStandard%20LDSC%7D%20%5Crightarrow%20%5Ctext%7Bs-LDSC%20/%20LDAK%20/%20%7D%5Calpha%5Ctext%7B-LDSC%7D"></p>
<p>Each step in this progression adds a more realistic piece of biology — first genome-wide relatedness instead of pedigree-based relatedness, then allowing MAF-dependence, then LD-density weighting, then functional-annotation-dependence. But every one of these methods shares a structural limitation: they’re all <strong>method-of-moments</strong> estimators, working “in expectation” over aggregate variance components. They can tell you the <em>total</em> (or category-partitioned) heritability very well — but they cannot tell you the posterior probability that any <em>individual</em> SNP is causal. If the true underlying architecture is spike-and-slab, LDSC-family methods simply can’t distinguish the spikes (null SNPs) from the slabs (causal SNPs).</p>
</section>
<section id="the-bridge-to-bayesian-methods" class="level2" data-number="9.3">
<h2 data-number="9.3" class="anchored" data-anchor-id="the-bridge-to-bayesian-methods"><span class="header-section-number">9.3</span> The Bridge to Bayesian Methods</h2>
<p>This is exactly the motivation for moving to a fully Bayesian framework — methods like <strong>SBayesRC</strong> (covered in depth in our companion PRS tutorial), which estimate a posterior effect size for <em>every individual SNP</em>, using:</p>
<ul>
<li><strong>Eigendecomposition</strong> of the LD matrix within pseudo-independent LD blocks, to make the computation tractable at genome scale — a direct computational descendant of the LD-score-based tricks used throughout this tutorial.</li>
<li>A <strong>four-component mixture prior</strong> (one zero-effect “spike,” three non-zero-variance “slabs”), extending the uniform-variance assumption of standard LDSC into an explicit, estimable distribution of effect sizes.</li>
<li><strong>Functional annotations</strong> modifying each SNP’s prior probability of a non-zero effect — the same heritability-enrichment logic from stratified LDSC (Part 6), now feeding directly into a Bayesian prior rather than just partitioning aggregate variance after the fact.</li>
</ul>
<p>In other words: everything in this tutorial builds toward being able to ask, and eventually answer, one final question — not just “how much of this trait is genetic?”, but “which specific variants are responsible?”</p>
<blockquote class="blockquote">
<p><strong>Final key takeaways</strong></p>
<ul>
<li>Heritability estimation methods form a continuous progression: individual-level (HE regression, GREML) → summary-statistics-based (LDSC and its many extensions) → fully Bayesian, variant-level (SBayesRC).</li>
<li>Genetic correlation is the natural two-trait extension of the same LD Score Regression machinery used for single-trait heritability.</li>
<li>Every method here — including cross-trait LDSC — comes with real, well-documented failure modes; checking sample size, ancestry matching, polygenicity, and liability-scale conversion before trusting a result is not optional.</li>
<li>LDSC-family methods excel at aggregate (genome-wide or per-category) variance estimation, but structurally cannot resolve individual-variant causality — which is precisely the gap that Bayesian polygenic methods were built to fill.</li>
</ul>
</blockquote>


</section>
</section>

 ]]></description>
  <category>Statistical Genetics</category>
  <category>Heritability</category>
  <category>Genetic Correlation</category>
  <category>LDSC</category>
  <category>Tutorial</category>
  <guid>https://bntechie.github.io/tutorials/Heritability_genetic_correlation/Heritability_and_Genetic_Correlation.html</guid>
  <pubDate>Sun, 26 Jul 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/Heritability_genetic_correlation/images/heritability-duality.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Survival Analysis: Deriving the Kaplan-Meier Estimator and the Cox Model From Scratch</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/survival_analysis/survival-analysis-tutorial.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/survival_analysis/images/survival-curves.svg" alt="Two step-function Kaplan-Meier survival curves for two groups, showing survival probability declining over time with a widening confidence band" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The shape every method in this tutorial is built to explain: a survival curve that steps down at each event, with uncertainty that widens as fewer people remain at risk.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">Kaplan-Meier</span> <span class="tag">Cox Model</span> <span class="tag">Survival Analysis</span> <span class="tag">R</span></p>
</div>
<section id="introduction" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="introduction"><span class="header-section-number">1</span> Introduction</h2>
<p>Suppose a new cancer treatment is introduced, and researchers want to know whether it helps patients live longer. They recruit volunteers, follow them for several years, and record when each patient experiences an event such as disease recurrence or death.</p>
<p>At first glance, this might seem like a straightforward prediction problem. Why not simply calculate the average survival time or fit a standard regression model?</p>
<p>The challenge is that real-world studies are not so straightforward. Some patients leave the study early, some are still alive when the study ends, and others are lost to follow-up. For these individuals, we know that the event has <strong>not yet occurred</strong>, but we do not know exactly <strong>when</strong> it eventually will. Ignoring these partially observed cases discards valuable information, while treating them as complete observations leads to biased conclusions.</p>
<p><strong>Survival analysis</strong> helps to solve this problem.</p>
<p>Survival analysis is designed to analyze <strong>time-to-event data</strong>—that is, data in which the outcome of interest is not simply <em>whether</em> an event occurs, but <strong>when</strong> it occurs. Although the name originated in medical research, where the event was often death or disease recurrence, the methodology applies to various situations involving the timing of an event.</p>
<p>Example cases:</p>
<ul>
<li>How long do cancer patients survive after treatment?</li>
<li>When does a patient experience disease relapse?</li>
<li>How long until a machine fails in a manufacturing plant?</li>
<li>When does a customer cancel a subscription service?</li>
<li>How long before a software system crashes?</li>
<li>When does a genetic mutation become fixed in a population?</li>
</ul>
<p>What makes these problems unique is that the timing of the event carries just as much information as the event itself.</p>
<p>A defining feature of survival data is <strong>censoring</strong>. Not every participant experiences the event during the observation period. For example, if a clinical trial ends after five years and a patient is still alive, we only know that their survival time is <strong>at least five years</strong>—their true survival time remains unknown. Classical statistical methods such as linear regression are not designed to handle these incomplete observations appropriately, whereas survival analysis incorporates them naturally, allowing researchers to use all available information without introducing systematic bias.</p>
<p>Over the past several decades, survival analysis has become one of the most important statistical tools in medicine, epidemiology, public health, engineering, economics, reliability analysis, and increasingly in data science and machine learning. Whether evaluating new therapies, estimating equipment reliability, modeling customer retention, or studying disease progression, the central question remains the same:</p>
<blockquote class="blockquote">
<p><strong>Given what we know today, how does the probability of experiencing an event change over time?</strong></p>
</blockquote>
<p>In this tutorial, we will build an intuitive understanding of the two foundational methods in survival analysis:</p>
<ul>
<li><strong>Kaplan–Meier estimation</strong>, which estimates the probability of surviving over time without assuming a specific statistical model.</li>
<li><strong>The Cox proportional hazards model</strong>, which quantifies how predictors such as age, treatment, or genetic factors influence the instantaneous risk of experiencing the event.</li>
</ul>
<p>We will try understand the statistical ideas and the underlying mathematics behind them , and implement each technique in <strong>R</strong> using some simple examples.</p>
</section>
<section id="basic-survival-quantities" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="basic-survival-quantities"><span class="header-section-number">2</span> Basic Survival Quantities</h2>
<p>Before learning the Kaplan–Meier estimator or the Cox proportional hazards model, it is important to understand the three mathematical quantities that form the foundation of survival analysis.</p>
<p>Suppose we follow an individual from the start of a study until an event occurs—for example, death, disease relapse, machine failure, or customer churn. The time until this event is called the <strong>survival time</strong> or <strong>event time</strong>.</p>
<p>We denote this event time by the random variable <img src="https://latex.codecogs.com/png.latex?T">.</p>
<p>Because different individuals experience the event at different times, we treat <img src="https://latex.codecogs.com/png.latex?T"> as a <strong>random variable</strong>, meaning that its exact value is uncertain before we observe it.</p>
<p>Survival analysis is built around three closely related functions:</p>
<ul>
<li><strong>The survival function</strong>, which tells us the probability that an individual remains event-free beyond a given time.</li>
<li><strong>The hazard function</strong>, which measures the instantaneous risk of experiencing the event at a particular moment, assuming the individual has survived up to that time.</li>
<li><strong>The cumulative hazard function</strong>, which accumulates this risk over time.</li>
</ul>
<p>Together, these three quantities describe the same underlying process from different perspectives.</p>
<section id="survival-function" class="level3" data-number="2.1">
<h3 data-number="2.1" class="anchored" data-anchor-id="survival-function"><span class="header-section-number">2.1</span> 1. Survival Function</h3>
<p>The most intuitive quantity is the <strong>survival function</strong>.</p>
<p>It answers the question:</p>
<blockquote class="blockquote">
<p><strong>What is the probability that an individual survives beyond time <img src="https://latex.codecogs.com/png.latex?t">?</strong></p>
</blockquote>
<p>Mathematically,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AS(t)=P(T%3Et)=1-F(t),%0A"></p>
<p>where</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?T"> is the event time,</li>
<li><img src="https://latex.codecogs.com/png.latex?F(t)"> is the cumulative distribution function (CDF), representing the probability that the event has already occurred by time <img src="https://latex.codecogs.com/png.latex?t">.</li>
</ul>
<p>As time increases, the survival probability can only stay the same or decrease.</p>
<hr>
</section>
<section id="hazard-function" class="level3" data-number="2.2">
<h3 data-number="2.2" class="anchored" data-anchor-id="hazard-function"><span class="header-section-number">2.2</span> 2. Hazard Function</h3>
<p>While the survival function describes the probability of remaining event-free, researchers are often interested in something slightly different:</p>
<blockquote class="blockquote">
<p><strong>Among individuals who have survived until time <img src="https://latex.codecogs.com/png.latex?t">, how likely is the event to occur immediately afterward?</strong></p>
</blockquote>
<p>This idea is captured by the <strong>hazard function</strong>, sometimes called the <strong>instantaneous event rate</strong> or <strong>instantaneous risk</strong>.</p>
<p>It is defined as</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ah(t)=%5Clim_%7B%5CDelta%20t%5Crightarrow0%7D%0A%5Cfrac%7BP(t%5Cle%20T%3Ct+%5CDelta%20t%5Cmid%20T%5Cge%20t)%7D%0A%7B%5CDelta%20t%7D.%0A"></p>
<p>Notice the conditioning.</p>
<p>The hazard is <strong>not</strong> the probability of dying at time <img src="https://latex.codecogs.com/png.latex?t">. Instead, it measures the instantaneous rate at which events occur among those who are still at risk just before time <img src="https://latex.codecogs.com/png.latex?t">.</p>
<p>This distinction is one of the most important concepts in survival analysis.</p>
<hr>
</section>
<section id="relationship-between-hazard-and-survival" class="level3" data-number="2.3">
<h3 data-number="2.3" class="anchored" data-anchor-id="relationship-between-hazard-and-survival"><span class="header-section-number">2.3</span> 3. Relationship Between Hazard and Survival</h3>
<p>Although the survival and hazard functions describe different ideas, they contain exactly the same information.</p>
<p>Starting from the definition of conditional probability,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ah(t)=%5Cfrac%7Bf(t)%7D%7BS(t)%7D,%0A"></p>
<p>where</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?f(t)"> is the probability density function (PDF),</li>
<li><img src="https://latex.codecogs.com/png.latex?S(t)"> is the survival function.</li>
</ul>
<p>Since</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Af(t)=-%5Cfrac%7BdS(t)%7D%7Bdt%7D,%0A"></p>
<p>we obtain</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ah(t)%0A=-%5Cfrac%7Bd%7D%7Bdt%7D%5Clog%20S(t).%0A"></p>
<p>This equation tells us that the hazard is simply the rate at which the logarithm of the survival probability decreases over time.</p>
<hr>
</section>
<section id="cumulative-hazard-function" class="level3" data-number="2.4">
<h3 data-number="2.4" class="anchored" data-anchor-id="cumulative-hazard-function"><span class="header-section-number">2.4</span> 4. Cumulative Hazard Function</h3>
<p>Rather than looking only at the instantaneous hazard, it is often useful to consider the <strong>total accumulated hazard</strong> up to time <img src="https://latex.codecogs.com/png.latex?t">.</p>
<p>This is called the <strong>cumulative hazard function</strong>:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH(t)%0A=%5Cint_0%5Et%20h(u),du.%0A"></p>
<p>Integrating the previous relationship gives</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH(t)%0A=-%5Clog%20S(t),%0A"></p>
<p>or equivalently,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AS(t)=%5Cexp%5B-H(t)%5D.%0A"></p>
<p>This elegant identity shows that the survival function and cumulative hazard function are simply two different mathematical representations of the same underlying phenomenon.</p>
<hr>
</section>
<section id="why-these-quantities-matter" class="level3" data-number="2.5">
<h3 data-number="2.5" class="anchored" data-anchor-id="why-these-quantities-matter"><span class="header-section-number">2.5</span> Why These Quantities Matter</h3>
<p>These definitions are more than mathematical formalities—they motivate the two most widely used methods in survival analysis.</p>
<ul>
<li><strong>Kaplan–Meier estimation</strong> focuses on estimating the survival function <img src="https://latex.codecogs.com/png.latex?S(t)"> directly from observed data.</li>
<li><strong>The Cox proportional hazards model</strong> focuses on modeling the hazard function <img src="https://latex.codecogs.com/png.latex?h(t)"> and how it changes with patient characteristics such as age, treatment, or genetic factors.</li>
</ul>
<p>Although the two methods approach the problem from different directions, they are linked through the relationship</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AS(t)=%5Cexp%5B-H(t)%5D.%0A"></p>
<p>Understanding this connection makes it much easier to see how the Kaplan–Meier estimator and the Cox model fit together within a single statistical framework.</p>
</section>
</section>
<section id="the-kaplanmeier-estimator" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="the-kaplanmeier-estimator"><span class="header-section-number">3</span> The Kaplan–Meier Estimator</h2>
<p>The <strong>Kaplan–Meier estimator</strong> is the most widely used non-parametric method for estimating the survival function from observed data.</p>
<p>Its goal is straightforward:</p>
<blockquote class="blockquote">
<p><strong>Given a group of individuals, what is the probability of remaining event-free over time?</strong></p>
</blockquote>
<p>Unlike parametric survival models, the Kaplan–Meier estimator makes <strong>no assumptions</strong> about the underlying distribution of survival times. Instead, it estimates the survival curve directly from the observed data while naturally accounting for censored observations.</p>
<section id="the-data-we-observe" class="level3" data-number="3.1">
<h3 data-number="3.1" class="anchored" data-anchor-id="the-data-we-observe"><span class="header-section-number">3.1</span> The Data We Observe</h3>
<p>In an ideal study, we would know the exact event time for every individual. In practice, however, this is rarely possible. Some participants experience the event during follow-up, while others are still event-free when the study ends or are lost to follow-up. For these individuals, we only know that the event occurs <strong>after</strong> their last observed time.</p>
<p>To accommodate this, survival analysis records two pieces of information for each individual:</p>
<ol type="1">
<li><strong>The observed follow-up time</strong></li>
<li><strong>Whether the event occurred during follow-up</strong></li>
</ol>
<p>Mathematically, for the <img src="https://latex.codecogs.com/png.latex?i">-th individual, we observe</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY_i=%5Cmin(T_i,C_i),%0A"></p>
<p>where</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?T_i"> is the true event time,</li>
<li><img src="https://latex.codecogs.com/png.latex?C_i"> is the censoring time,</li>
<li><img src="https://latex.codecogs.com/png.latex?Y_i"> is the observed follow-up time, equal to whichever occurs first.</li>
</ul>
<p>We also define an <strong>event indicator</strong></p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cdelta_i=%0A%5Cbegin%7Bcases%7D%0A1,%20&amp;%20%5Ctext%7Bif%20the%20event%20occurred%7D,%5C%0A0,%20&amp;%20%5Ctext%7Bif%20the%20observation%20was%20censored%7D.%0A%5Cend%7Bcases%7D%0A"></p>
<p>Thus, each observation consists of the pair <img src="https://latex.codecogs.com/png.latex?(Y_i,%5Cdelta_i)">.</p>
<hr>
</section>
<section id="constructing-the-risk-set" class="level3" data-number="3.2">
<h3 data-number="3.2" class="anchored" data-anchor-id="constructing-the-risk-set"><span class="header-section-number">3.2</span> Constructing the Risk Set</h3>
<p>The Kaplan–Meier estimator builds the survival curve one event time at a time.</p>
<p>Suppose the distinct observed event times are</p>
<p><img src="https://latex.codecogs.com/png.latex?%0At_1,t_2,%5Cldots,t_k.%0A"></p>
<p>Immediately before each event time <img src="https://latex.codecogs.com/png.latex?t_j">, we define two important quantities:</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?n_j">: the number of individuals <strong>at risk</strong> just before <img src="https://latex.codecogs.com/png.latex?t_j">.</li>
<li><img src="https://latex.codecogs.com/png.latex?d_j">: the number of events occurring exactly at <img src="https://latex.codecogs.com/png.latex?t_j">.</li>
</ul>
<p>An individual is considered <strong>at risk</strong> if they have not experienced the event or been censored before time <img src="https://latex.codecogs.com/png.latex?t_j">. Equivalently,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY_i%20%5Cge%20t_j.%0A"></p>
<p>Notice that individuals who are censored <strong>after</strong> <img src="https://latex.codecogs.com/png.latex?t_j"> still belong to the risk set at time <img src="https://latex.codecogs.com/png.latex?t_j">, because they were under observation until that point.</p>
<hr>
</section>
<section id="deriving-the-kaplanmeier-estimator" class="level3" data-number="3.3">
<h3 data-number="3.3" class="anchored" data-anchor-id="deriving-the-kaplanmeier-estimator"><span class="header-section-number">3.3</span> Deriving the Kaplan–Meier Estimator</h3>
<p>The key idea is simple.</p>
<p>To survive beyond time <img src="https://latex.codecogs.com/png.latex?t">, an individual must survive <strong>every earlier event time</strong>. Therefore, the overall survival probability can be written as the product of conditional survival probabilities:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AS(t)%0A=%5Cprod_%7Bt_j%5Cle%20t%7D%0AP(T%3Et_j%20%5Cmid%20T%5Cge%20t_j).%0A"></p>
<p>At each event time <img src="https://latex.codecogs.com/png.latex?t_j">,</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?n_j"> individuals are at risk,</li>
<li><img src="https://latex.codecogs.com/png.latex?d_j"> experience the event.</li>
</ul>
<p>The empirical probability of experiencing the event at that instant is therefore</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7Bd_j%7D%7Bn_j%7D,%0A"></p>
<p>so the empirical probability of surviving beyond that event time is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A1-%5Cfrac%7Bd_j%7D%7Bn_j%7D.%0A"></p>
<p>Multiplying these conditional survival probabilities across all event times gives the Kaplan–Meier estimator:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cboxed%7B%0A%5Chat%20S(t)%0A=%5Cprod_%7Bt_j%5Cle%20t%7D%0A%5Cleft(%0A1-%5Cfrac%7Bd_j%7D%7Bn_j%7D%0A%5Cright)%0A%7D%0A"></p>
<p>This estimator is called the <strong>product-limit estimator</strong> because it is obtained by multiplying together successive conditional survival probabilities.</p>
<hr>
</section>
<section id="why-does-the-survival-curve-look-like-a-staircase" class="level3" data-number="3.4">
<h3 data-number="3.4" class="anchored" data-anchor-id="why-does-the-survival-curve-look-like-a-staircase"><span class="header-section-number">3.4</span> Why Does the Survival Curve Look Like a Staircase?</h3>
<p>The Kaplan–Meier estimator is a <strong>step function</strong>.</p>
<p>The survival probability changes <strong>only when an event occurs</strong>.</p>
<p>Censored observations do <strong>not</strong> produce downward steps because no event has occurred. Instead, censored individuals are simply removed from the risk set for subsequent event times, reducing the denominator <img src="https://latex.codecogs.com/png.latex?n_j"> in later calculations.</p>
<p>Consequently,</p>
<ul>
<li>observed events produce downward steps,</li>
<li>censoring affects future risk sets but does not immediately change the estimated survival probability.</li>
</ul>
<hr>
</section>
<section id="implementing-the-kaplanmeier-estimator-in-r" class="level3" data-number="3.5">
<h3 data-number="3.5" class="anchored" data-anchor-id="implementing-the-kaplanmeier-estimator-in-r"><span class="header-section-number">3.5</span> Implementing the Kaplan–Meier Estimator in R</h3>
<p>The following example implements the Kaplan–Meier estimator directly from its mathematical definition.</p>
<p>We begin with a small toy dataset containing both observed events (<code>status = 1</code>) and censored observations (<code>status = 0</code>). For each distinct event time, we calculate</p>
<ul>
<li>the number of individuals at risk (<img src="https://latex.codecogs.com/png.latex?n_j">),</li>
<li>the number of observed events (<img src="https://latex.codecogs.com/png.latex?d_j">),</li>
<li>the updated survival probability using the product-limit formula.</li>
</ul>
<p>Finally, we compare our manual calculation with the result produced by the <code>survfit()</code> function from R’s <strong>survival</strong> package. Both methods should produce identical survival estimates, demonstrating that the Kaplan–Meier estimator implemented by <code>survfit()</code> is simply an efficient implementation of the mathematical definition derived above.</p>
<div id="9f89447c-348f-4c59-bd80-f12e21b267bb" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:21.554893Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:21.539987Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:23.815644Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:23.808382Z&quot;}}" data-execution_count="1">
<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>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(survival)</span>
<span id="cb1-3">toy <span class="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="cb1-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">time   =</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;">4</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;">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;">9</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;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>),</span>
<span id="cb1-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">status =</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;">1</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;">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;">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;">1</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 = event, 0 = censored</span></span>
<span id="cb1-6">)</span>
<span id="cb1-7"></span>
<span id="cb1-8">toy</span>
<span id="cb1-9"></span>
<span id="cb1-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Distinct event times</span></span>
<span id="cb1-11">event_times <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sort</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(toy<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time[toy<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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="cb1-12"></span>
<span id="cb1-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Manual Kaplan–Meier calculation</span></span>
<span id="cb1-14">km_manual <span class="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="cb1-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">time =</span> event_times,</span>
<span id="cb1-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>,</span>
<span id="cb1-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>,</span>
<span id="cb1-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">S =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span></span>
<span id="cb1-19">)</span>
<span id="cb1-20"></span>
<span id="cb1-21">S <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-22"></span>
<span id="cb1-23"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <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>(event_times)) {</span>
<span id="cb1-24"></span>
<span id="cb1-25">  tj  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> event_times[i]</span>
<span id="cb1-26"></span>
<span id="cb1-27">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number at risk immediately before tj</span></span>
<span id="cb1-28">  n_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;">sum</span>(toy<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> tj)</span>
<span id="cb1-29"></span>
<span id="cb1-30">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of events at tj</span></span>
<span id="cb1-31">  d_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;">sum</span>(toy<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> tj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> toy<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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="cb1-32"></span>
<span id="cb1-33">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Product-limit update</span></span>
<span id="cb1-34">  S <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> (<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_j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_j)</span>
<span id="cb1-35"></span>
<span id="cb1-36">  km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n[i] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_j</span>
<span id="cb1-37">  km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>d[i] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> d_j</span>
<span id="cb1-38">  km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>S[i] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> S</span>
<span id="cb1-39">}</span>
<span id="cb1-40"></span>
<span id="cb1-41">km_manual</span>
<span id="cb1-42"></span>
<span id="cb1-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compare with survfit()</span></span>
<span id="cb1-44">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;">survfit</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Surv</span>(time, status) <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;">data =</span> toy)</span>
<span id="cb1-45"></span>
<span id="cb1-46">comparison <span class="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="cb1-47">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">time =</span> event_times,</span>
<span id="cb1-48">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">manual =</span> km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>S,</span>
<span id="cb1-49">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">survfit =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(fit)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>surv</span>
<span id="cb1-50">)</span>
<span id="cb1-51"></span>
<span id="cb1-52">comparison</span>
<span id="cb1-53"></span>
<span id="cb1-54"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 10 × 2</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">time</th>
<th data-quarto-table-cell-role="th" scope="col">status</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>4</td>
<td>1</td>
</tr>
<tr class="even">
<td>6</td>
<td>1</td>
</tr>
<tr class="odd">
<td>6</td>
<td>0</td>
</tr>
<tr class="even">
<td>8</td>
<td>1</td>
</tr>
<tr class="odd">
<td>9</td>
<td>0</td>
</tr>
<tr class="even">
<td>10</td>
<td>1</td>
</tr>
<tr class="odd">
<td>11</td>
<td>0</td>
</tr>
<tr class="even">
<td>14</td>
<td>1</td>
</tr>
<tr class="odd">
<td>14</td>
<td>1</td>
</tr>
<tr class="even">
<td>18</td>
<td>0</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 5 × 4</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">time</th>
<th data-quarto-table-cell-role="th" scope="col">n</th>
<th data-quarto-table-cell-role="th" scope="col">d</th>
<th data-quarto-table-cell-role="th" scope="col">S</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>4</td>
<td>10</td>
<td>1</td>
<td>0.9000000</td>
</tr>
<tr class="even">
<td>6</td>
<td>9</td>
<td>1</td>
<td>0.8000000</td>
</tr>
<tr class="odd">
<td>8</td>
<td>7</td>
<td>1</td>
<td>0.6857143</td>
</tr>
<tr class="even">
<td>10</td>
<td>5</td>
<td>1</td>
<td>0.5485714</td>
</tr>
<tr class="odd">
<td>14</td>
<td>3</td>
<td>2</td>
<td>0.1828571</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 5 × 3</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">time</th>
<th data-quarto-table-cell-role="th" scope="col">manual</th>
<th data-quarto-table-cell-role="th" scope="col">survfit</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>4</td>
<td>0.9000000</td>
<td>0.9000000</td>
</tr>
<tr class="even">
<td>6</td>
<td>0.8000000</td>
<td>0.8000000</td>
</tr>
<tr class="odd">
<td>8</td>
<td>0.6857143</td>
<td>0.6857143</td>
</tr>
<tr class="even">
<td>10</td>
<td>0.5485714</td>
<td>0.5485714</td>
</tr>
<tr class="odd">
<td>14</td>
<td>0.1828571</td>
<td>0.1828571</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The <code>comparison</code> table shows that the manually computed survival probabilities exactly match those returned by <code>survfit()</code>. This confirms that the Kaplan–Meier estimator is simply the cumulative product of conditional survival probabilities evaluated at each observed event time.</p>
<p>The manually computed survival probabilities match those returned by <code>survfit()</code> exactly at every event time, confirming that the Kaplan–Meier estimator implemented in R is simply an efficient implementation of the product-limit formula derived above.</p>
<blockquote class="blockquote">
<p><strong>Why does the survival curve drop by different amounts at each event time?</strong></p>
<p>The size of each downward step depends on the proportion of individuals who experience the event, not simply on the number of events. At event time <img src="https://latex.codecogs.com/png.latex?t_j">, the drop is determined by</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7Bd_j%7D%7Bn_j%7D,%0A"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?d_j"> is the number of events and <img src="https://latex.codecogs.com/png.latex?n_j"> is the number of individuals still at risk. Consequently, two events among only three individuals at risk produce a much larger decrease in the survival probability than one event among nine individuals at risk.</p>
</blockquote>
</section>
<section id="visualizing-the-kaplanmeier-survival-curve" class="level3" data-number="3.6">
<h3 data-number="3.6" class="anchored" data-anchor-id="visualizing-the-kaplanmeier-survival-curve"><span class="header-section-number">3.6</span> Visualizing the Kaplan–Meier Survival Curve</h3>
<p>The Kaplan–Meier estimate is conventionally displayed as a step function. The curve drops at observed event times and remains unchanged between events. Vertical marks indicate censored observations: these individuals were still event-free at their last recorded follow-up time, but their subsequent outcomes are unknown.</p>
<div id="39068095-cc9a-430d-9b6a-e307f26d09e6" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:23.962026Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:23.826899Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.132767Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.127378Z&quot;}}" data-execution_count="2">
<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"></span>
<span id="cb2-2"></span>
<span id="cb2-3">km_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;">survfit</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Surv</span>(time, status) <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;">data =</span> lung)</span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb2-6">  km_fit,</span>
<span id="cb2-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Time"</span>,</span>
<span id="cb2-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Estimated survival probability"</span>,</span>
<span id="cb2-9">  <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;">"Kaplan–Meier Survival Curve"</span>,</span>
<span id="cb2-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mark.time =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb2-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">conf.int =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb2-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lwd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb2-13">)</span>
<span id="cb2-14"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/survival_analysis/survival-analysis-tutorial_files/figure-html/cell-3-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The estimated survival probability declines over follow-up as deaths occur. The widening confidence interval toward the right-hand tail reflects the decreasing number of individuals remaining under observation. ### Quantifying Uncertainty: Greenwood’s Formula</p>
<p>The Kaplan–Meier estimator provides a <strong>point estimate</strong> of the survival probability. As with any statistical estimate, however, we also want to know <strong>how precise</strong> that estimate is.</p>
<p>The uncertainty of the Kaplan–Meier estimator is estimated using <strong>Greenwood’s formula</strong>, which provides an estimate of its variance:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cwidehat%7B%5Cmathrm%7BVar%7D%7D%7B%5Chat%20S(t)%7D%0A=%5Chat%20S(t)%5E2%0A%5Csum_%7Bt_j%5Cle%20t%7D%0A%5Cfrac%7Bd_j%7D%0A%7Bn_j(n_j-d_j)%7D.%0A"></p>
<p>Taking the square root gives the estimated standard error:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cwidehat%7B%5Cmathrm%7BSE%7D%7D%7B%5Chat%20S(t)%7D%0A=%5Chat%20S(t)%0A%5Csqrt%7B%0A%5Csum_%7Bt_j%5Cle%20t%7D%0A%5Cfrac%7Bd_j%7D%0A%7Bn_j(n_j-d_j)%7D%0A%7D.%0A"></p>
<p>Each observed event contributes one term to the summation. As follow-up continues and fewer individuals remain in the risk set, the uncertainty of the survival estimate generally increases. This is why confidence intervals around Kaplan–Meier curves typically become wider toward the end of a study.</p>
</section>
<section id="implementing-greenwoods-formula" class="level3" data-number="3.7">
<h3 data-number="3.7" class="anchored" data-anchor-id="implementing-greenwoods-formula"><span class="header-section-number">3.7</span> Implementing Greenwood’s Formula</h3>
<p>Just as we manually computed the Kaplan–Meier estimator, we can also compute its standard error directly from Greenwood’s formula.</p>
<p>At each event time we:</p>
<ol type="1">
<li>Update the Kaplan–Meier survival estimate.</li>
<li>Add the Greenwood variance contribution <img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7Bd_j%7D%7Bn_j(n_j-d_j)%7D%0A"> to a running cumulative sum.</li>
<li>Multiply the accumulated variance term by the current survival estimate to obtain the standard error.</li>
</ol>
<p>The implementation below follows these three steps directly.</p>
<div id="0e10f954-640d-421a-96c8-28770988d9fd" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.139019Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.137035Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.181187Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.178596Z&quot;}}" data-execution_count="3">
<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;"># Manual Greenwood standard error</span></span>
<span id="cb3-2">S <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="cb3-3">cum_var_term <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>
<span id="cb3-4"></span>
<span id="cb3-5">km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>se <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;">NA</span></span>
<span id="cb3-6"></span>
<span id="cb3-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <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>(event_times)) {</span>
<span id="cb3-8"></span>
<span id="cb3-9">  n_j <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n[i]</span>
<span id="cb3-10">  d_j <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>d[i]</span>
<span id="cb3-11"></span>
<span id="cb3-12">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Update Kaplan–Meier estimate</span></span>
<span id="cb3-13">  S <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> (<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_j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_j)</span>
<span id="cb3-14"></span>
<span id="cb3-15">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Greenwood variance contribution</span></span>
<span id="cb3-16">  cum_var_term <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cum_var_term <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-17">    d_j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (n_j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (n_j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> d_j))</span>
<span id="cb3-18"></span>
<span id="cb3-19">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Standard error</span></span>
<span id="cb3-20">  km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>se[i] <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> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(cum_var_term)</span>
<span id="cb3-21"></span>
<span id="cb3-22">}</span>
<span id="cb3-23"></span>
<span id="cb3-24">km_manual[, <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;">"time"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"S"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"se"</span>)]</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 5 × 3</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">time</th>
<th data-quarto-table-cell-role="th" scope="col">S</th>
<th data-quarto-table-cell-role="th" scope="col">se</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>4</td>
<td>0.9000000</td>
<td>0.09486833</td>
</tr>
<tr class="even">
<td>6</td>
<td>0.8000000</td>
<td>0.12649111</td>
</tr>
<tr class="odd">
<td>8</td>
<td>0.6857143</td>
<td>0.15149402</td>
</tr>
<tr class="even">
<td>10</td>
<td>0.5485714</td>
<td>0.17243785</td>
</tr>
<tr class="odd">
<td>14</td>
<td>0.1828571</td>
<td>0.15998445</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>We can now compare both the manually calculated survival probabilities and their standard errors with the values returned by <code>survfit()</code>.</p>
<div id="db10b208" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.186779Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.185026Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.216029Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.213645Z&quot;}}" data-execution_count="4">
<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">comparison <span class="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="cb4-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">time =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(fit)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time,</span>
<span id="cb4-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">manual_surv =</span> km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>S,</span>
<span id="cb4-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">survfit_surv =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(fit)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>surv,</span>
<span id="cb4-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">manual_se =</span> km_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>se,</span>
<span id="cb4-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">survfit_se =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(fit)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>std.err</span>
<span id="cb4-7">)</span>
<span id="cb4-8">comparison</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 5 × 5</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">time</th>
<th data-quarto-table-cell-role="th" scope="col">manual_surv</th>
<th data-quarto-table-cell-role="th" scope="col">survfit_surv</th>
<th data-quarto-table-cell-role="th" scope="col">manual_se</th>
<th data-quarto-table-cell-role="th" scope="col">survfit_se</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>4</td>
<td>0.9000000</td>
<td>0.9000000</td>
<td>0.09486833</td>
<td>0.09486833</td>
</tr>
<tr class="even">
<td>6</td>
<td>0.8000000</td>
<td>0.8000000</td>
<td>0.12649111</td>
<td>0.12649111</td>
</tr>
<tr class="odd">
<td>8</td>
<td>0.6857143</td>
<td>0.6857143</td>
<td>0.15149402</td>
<td>0.15149402</td>
</tr>
<tr class="even">
<td>10</td>
<td>0.5485714</td>
<td>0.5485714</td>
<td>0.17243785</td>
<td>0.17243785</td>
</tr>
<tr class="odd">
<td>14</td>
<td>0.1828571</td>
<td>0.1828571</td>
<td>0.15998445</td>
<td>0.15998445</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The manually calculated survival probabilities and standard errors should match those returned by <code>survfit()</code> to numerical precision. This demonstrates that the Kaplan–Meier estimator and Greenwood’s standard error are not separate algorithms, but rather direct implementations of the mathematical formulas derived above.</p>
</section>
</section>
<section id="the-cox-proportional-hazards-model" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="the-cox-proportional-hazards-model"><span class="header-section-number">4</span> The Cox Proportional Hazards Model</h2>
<p>The Kaplan–Meier estimator is an excellent tool for estimating the survival probability of a group over time. However, it has one important limitation: it cannot simultaneously evaluate the effect of multiple variables on survival.</p>
<p>Suppose we want to answer questions such as:</p>
<ul>
<li>Does age increase the risk of death?</li>
<li>Is a new treatment more effective than the standard treatment?</li>
<li>Does smoking shorten survival after accounting for age?</li>
<li>Do specific genetic variants influence disease progression?</li>
</ul>
<p>These questions involve <strong>covariates</strong>—variables that may influence the time until an event occurs. While Kaplan–Meier curves can compare a few predefined groups (for example, treated versus untreated patients), they cannot quantify the effect of several predictors simultaneously.</p>
<p>To address this problem, Sir David Cox introduced the <strong>Cox proportional hazards model</strong> in 1972. Rather than modeling the survival probability directly, the Cox model describes <strong>how covariates influence the hazard</strong>, or instantaneous risk, of experiencing the event.</p>
<section id="the-cox-model" class="level3" data-number="4.1">
<h3 data-number="4.1" class="anchored" data-anchor-id="the-cox-model"><span class="header-section-number">4.1</span> The Cox Model</h3>
<p>For an individual with covariate vector <img src="https://latex.codecogs.com/png.latex?X_i">, the hazard function is written as</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ah_i(t%20%5Cmid%20X_i)%0A=h_0(t)%5Cexp(%5Cbeta%5ET%20X_i),%0A"></p>
<p>where</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?h_i(t)"> is the hazard for individual <img src="https://latex.codecogs.com/png.latex?i">,</li>
<li><img src="https://latex.codecogs.com/png.latex?h_0(t)"> is the <strong>baseline hazard</strong>, representing the hazard when all covariates are at their reference values,</li>
<li><img src="https://latex.codecogs.com/png.latex?X_i"> is the vector of observed covariates (such as age, sex, or treatment),</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Cbeta"> is the vector of regression coefficients describing how each covariate affects the hazard.</li>
</ul>
<p>The exponential function ensures that the hazard remains positive while allowing covariates to increase or decrease the risk multiplicatively.</p>
<hr>
</section>
<section id="hazard-ratios" class="level3" data-number="4.2">
<h3 data-number="4.2" class="anchored" data-anchor-id="hazard-ratios"><span class="header-section-number">4.2</span> Hazard Ratios</h3>
<p>One of the most attractive features of the Cox model is that we can compare two individuals without knowing the baseline hazard.</p>
<p>Suppose individuals <strong>A</strong> and <strong>B</strong> have covariate vectors <img src="https://latex.codecogs.com/png.latex?X_A"> and <img src="https://latex.codecogs.com/png.latex?X_B">. Their hazard ratio is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7Bh(t%5Cmid%20X_A)%7D%0A%7Bh(t%5Cmid%20X_B)%7D%0A=%5Cexp%7B%5Cbeta%5ET(X_A-X_B)%7D.%0A"></p>
<p>Notice that the baseline hazard <img src="https://latex.codecogs.com/png.latex?h_0(t)"> cancels completely.</p>
<p>This means that the Cox model estimates <strong>relative risk</strong>, rather than absolute risk.</p>
<p>For example, if</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cexp(%5Cbeta)=2,%0A"></p>
<p>then one individual has <strong>twice the instantaneous risk</strong> of experiencing the event compared with another individual who differs by one unit in that covariate.</p>
<hr>
</section>
<section id="why-is-it-called-the-proportional-hazards-model" class="level3" data-number="4.3">
<h3 data-number="4.3" class="anchored" data-anchor-id="why-is-it-called-the-proportional-hazards-model"><span class="header-section-number">4.3</span> Why Is It Called the Proportional Hazards Model?</h3>
<p>The hazard ratio above does <strong>not</strong> depend on time.</p>
<p>Regardless of whether the baseline hazard increases, decreases, or fluctuates during follow-up, the ratio between two individuals remains constant:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7Bh(t%5Cmid%20X_A)%7D%0A%7Bh(t%5Cmid%20X_B)%7D%0A=%5Ctext%7Bconstant%7D.%0A"></p>
<p>This assumption is known as the <strong>proportional hazards assumption</strong>, and it gives the model its name.</p>
<p>Importantly, this is an <strong>assumption</strong>, not a mathematical guarantee. In practice, it should always be assessed after fitting the model, most commonly using <strong>Schoenfeld residuals</strong>, which we will discuss later.</p>
<hr>
</section>
<section id="coxs-key-insight-the-partial-likelihood" class="level3" data-number="4.4">
<h3 data-number="4.4" class="anchored" data-anchor-id="coxs-key-insight-the-partial-likelihood"><span class="header-section-number">4.4</span> Cox’s Key Insight: The Partial Likelihood</h3>
<p>At first glance, estimating the regression coefficients appears difficult because the baseline hazard <img src="https://latex.codecogs.com/png.latex?h_0(t)"> is completely unknown.</p>
<p>Cox’s key insight was that we do not actually need to estimate the baseline hazard in order to estimate the regression coefficients.</p>
<p>Instead of modeling the full likelihood, he considered the probability that, among all individuals still at risk at an observed event time, the individual who actually experienced the event was the one who failed.</p>
<p>Suppose individual <img src="https://latex.codecogs.com/png.latex?i_j"> experiences the event at time <img src="https://latex.codecogs.com/png.latex?t_j">, and let <img src="https://latex.codecogs.com/png.latex?R(t_j)"> denote the <strong>risk set</strong>—the individuals still under observation immediately before that event time.</p>
<p>The conditional probability that individual <img src="https://latex.codecogs.com/png.latex?i_j"> experiences the event is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(i_j%5Ctext%7B%20fails%20at%20%7Dt_j%0A%5Cmid%0A%5Ctext%7Bone%20failure%20in%20%7DR(t_j))%0A=%5Cfrac%7B%5Cexp(%5Cbeta%5ET%20X_%7Bi_j%7D)%7D%0A%7B%5Csum_%7Bl%5Cin%20R(t_j)%7D%0A%5Cexp(%5Cbeta%5ET%20X_l)%7D.%0A"></p>
<p>Remarkably, the unknown baseline hazard cancels from this expression, just as it did in the hazard ratio.</p>
<p>Multiplying these conditional probabilities across all observed event times produces the <strong>partial likelihood</strong>:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AL_p(%5Cbeta)%0A=%5Cprod_%7Bj=1%7D%5E%7Bk%7D%0A%5Cfrac%7B%5Cexp(%5Cbeta%5ET%20X_%7Bi_j%7D)%7D%0A%7B%5Csum_%7Bl%5Cin%20R(t_j)%7D%0A%5Cexp(%5Cbeta%5ET%20X_l)%7D.%0A"></p>
<p>Unlike an ordinary likelihood, the partial likelihood contains only the regression coefficients and no baseline hazard, making estimation much simpler.</p>
<hr>
</section>
<section id="estimating-the-regression-coefficients" class="level3" data-number="4.5">
<h3 data-number="4.5" class="anchored" data-anchor-id="estimating-the-regression-coefficients"><span class="header-section-number">4.5</span> Estimating the Regression Coefficients</h3>
<p>To estimate the regression coefficients, we maximize the <strong>log partial likelihood</strong> numerically.</p>
<p>This produces the estimate</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%7B%5Cbeta%7D,%0A"></p>
<p>which quantifies the effect of each covariate on the hazard.</p>
<p>Modern statistical software performs this optimization automatically. In R, the <code>coxph()</code> function from the <strong>survival</strong> package fits the Cox proportional hazards model using this partial likelihood approach.</p>
<p>To better understand how the method works, the following example first implements the log partial likelihood directly from its mathematical definition and optimizes it using <code>optim()</code>. We then compare the manually estimated regression coefficients with those returned by <code>coxph()</code> using the <code>lung</code> dataset and two covariates: <strong>age</strong> and <strong>sex</strong>.</p>
</section>
<section id="implementing-the-cox-partial-likelihood-by-hand" class="level3" data-number="4.6">
<h3 data-number="4.6" class="anchored" data-anchor-id="implementing-the-cox-partial-likelihood-by-hand"><span class="header-section-number">4.6</span> Implementing the Cox Partial Likelihood by Hand</h3>
<p>We now implement the Cox partial likelihood directly from its mathematical definition. We use the <code>lung</code> dataset from the <strong>survival</strong> package and model survival using age and sex.</p>
<p>In the original dataset:</p>
<ul>
<li><code>status = 1</code> indicates censoring and <code>status = 2</code> indicates death.</li>
<li><code>sex = 1</code> indicates male and <code>sex = 2</code> indicates female.</li>
</ul>
<p>We recode both variables into a more conventional binary form:</p>
<ul>
<li><code>status = 0</code> for censored and <code>status = 1</code> for an observed event.</li>
<li><code>sex = 0</code> for male and <code>sex = 1</code> for female.</li>
</ul>
<div id="fbc05fe6-cd99-4d6b-ae2a-c019d03e78d5" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.221530Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.219547Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.238301Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.235876Z&quot;}}" data-execution_count="5">
<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>
<span id="cb5-2">lung2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>(lung[, <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;">"time"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"age"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>)])</span>
<span id="cb5-3"></span>
<span id="cb5-4">lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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;"># 0 = censored, 1 = event</span></span>
<span id="cb5-5">lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sex    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sex <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;"># 0 = male, 1 = female</span></span></code></pre></div></div>
</div>
<p>The function below calculates the negative log partial likelihood. For each distinct event time, it identifies:</p>
<ul>
<li>the individuals still in the risk set,</li>
<li>the individuals experiencing the event,</li>
<li>the linear predictor <img src="https://latex.codecogs.com/png.latex?%5Cbeta%5ET%20X"> for everyone in the risk set.</li>
</ul>
<p>It then adds each event’s contribution to the log partial likelihood:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cell_p(%5Cbeta)%0A=%5Csum_%7Bj%7D%5Cleft%5B%5Cbeta%5ET%20X_%7Bi_j%7D-%5Clog%5Cleft%7B%5Csum_%7Bl%5Cin%20R(t_j)%7D%5Cexp(%5Cbeta%5ET%20X_l)%5Cright%7D%5Cright%5D.%0A"></p>
<div id="fa285b59-f0ac-46ad-bee1-88d54657a7cd" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.244161Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.242038Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.257705Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.255222Z&quot;}}" data-execution_count="6">
<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>
<span id="cb6-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Negative log partial likelihood</span></span>
<span id="cb6-3">neg_log_pl <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>(beta, data) {</span>
<span id="cb6-4"></span>
<span id="cb6-5">  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.matrix</span>(data[, <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;">"age"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>)])</span>
<span id="cb6-6">  time <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time</span>
<span id="cb6-7">  status <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status</span>
<span id="cb6-8"></span>
<span id="cb6-9">  event_times <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sort</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(time[status <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-10"></span>
<span id="cb6-11">  log_partial_likelihood <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>
<span id="cb6-12"></span>
<span id="cb6-13">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (tj <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> event_times) {</span>
<span id="cb6-14"></span>
<span id="cb6-15">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Individuals still at risk immediately before tj</span></span>
<span id="cb6-16">    risk_idx <span class="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>(time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> tj)</span>
<span id="cb6-17"></span>
<span id="cb6-18">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Individuals experiencing the event at tj</span></span>
<span id="cb6-19">    event_idx <span class="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>(time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> tj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> status <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-20"></span>
<span id="cb6-21">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Linear predictors for the risk set</span></span>
<span id="cb6-22">    linear_predictor <span class="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.vector</span>(</span>
<span id="cb6-23">      X[risk_idx, , <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> beta</span>
<span id="cb6-24">    )</span>
<span id="cb6-25"></span>
<span id="cb6-26">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add one contribution for each event at tj</span></span>
<span id="cb6-27">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> event_idx) {</span>
<span id="cb6-28"></span>
<span id="cb6-29">      log_partial_likelihood <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb6-30">        log_partial_likelihood <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-31">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(X[i, ] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> beta) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span></span>
<span id="cb6-32">        <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;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(linear_predictor)))</span>
<span id="cb6-33">    }</span>
<span id="cb6-34">  }</span>
<span id="cb6-35"></span>
<span id="cb6-36">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># optim() minimizes, so return the negative value</span></span>
<span id="cb6-37">  <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>log_partial_likelihood</span>
<span id="cb6-38">}</span>
<span id="cb6-39"></span>
<span id="cb6-40"></span>
<span id="cb6-41"></span></code></pre></div></div>
</div>
<p>We use <code>optim()</code> to minimize the negative log partial likelihood. The Hessian matrix returned by the optimizer provides an estimate of the covariance matrix of the regression coefficients.</p>
<div id="d978a3f7-de54-4119-81de-8e101d347d6d" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.264098Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.261659Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.709295Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.705752Z&quot;}}" data-execution_count="7">
<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>
<span id="cb7-2">fit_manual <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optim</span>(</span>
<span id="cb7-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">par =</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;">0</span>),</span>
<span id="cb7-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fn =</span> neg_log_pl,</span>
<span id="cb7-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> lung2,</span>
<span id="cb7-6">  <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;">"BFGS"</span>,</span>
<span id="cb7-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hessian =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb7-8">)</span>
<span id="cb7-9"></span>
<span id="cb7-10">beta_manual <span class="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>
<span id="cb7-11">  fit_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>par,</span>
<span id="cb7-12">  <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;">"age"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>)</span>
<span id="cb7-13">)</span>
<span id="cb7-14"></span>
<span id="cb7-15">se_manual <span class="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>
<span id="cb7-16">  <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;">diag</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">solve</span>(fit_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hessian))),</span>
<span id="cb7-17">  <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;">"age"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>)</span>
<span id="cb7-18">)</span>
<span id="cb7-19"></span>
<span id="cb7-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(beta_manual, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb7-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(se_manual, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>age</dt><dd>0.017</dd><dt>sex</dt><dd>-0.5126</dd></dl>
</div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>age</dt><dd>0.0092</dd><dt>sex</dt><dd>0.1675</dd></dl>
</div>
</div>
</section>
<section id="handling-tied-event-times" class="level3" data-number="4.7">
<h3 data-number="4.7" class="anchored" data-anchor-id="handling-tied-event-times"><span class="header-section-number">4.7</span> Handling Tied Event Times</h3>
<p>In real survival datasets, multiple individuals may experience the event at exactly the same recorded time. These are called <strong>tied events</strong>.</p>
<p>The manual implementation above uses the <strong>Breslow approximation</strong>: all events occurring at the same time share the same risk-set denominator.</p>
<p>To make the comparison technically consistent, we must therefore instruct <code>coxph()</code> to use the same method:</p>
<div id="5f4ea781-3b8e-472b-82a0-e032351f3fac" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.714863Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.712837Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.744843Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.742707Z&quot;}}" data-execution_count="8">
<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">fit_cox <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coxph</span>(</span>
<span id="cb8-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Surv</span>(time, status) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> age <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> sex,</span>
<span id="cb8-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> lung2,</span>
<span id="cb8-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ties =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"breslow"</span></span>
<span id="cb8-5">)</span>
<span id="cb8-6"></span>
<span id="cb8-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(fit_cox)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>Call:
coxph(formula = Surv(time, status) ~ age + sex, data = lung2, 
    ties = "breslow")

  n= 228, number of events= 165 

         coef exp(coef)  se(coef)      z Pr(&gt;|z|)   
age  0.017013  1.017158  0.009222  1.845  0.06506 . 
sex -0.512565  0.598957  0.167462 -3.061  0.00221 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

    exp(coef) exp(-coef) lower .95 upper .95
age     1.017     0.9831    0.9989    1.0357
sex     0.599     1.6696    0.4314    0.8316

Concordance= 0.603  (se = 0.025 )
Likelihood ratio test= 14.08  on 2 df,   p=9e-04
Wald test            = 13.44  on 2 df,   p=0.001
Score (logrank) test = 13.69  on 2 df,   p=0.001</code></pre>
</div>
</div>
<p>We can compare the manually estimated coefficients and standard errors with those returned by <code>coxph()</code>:</p>
<div id="e8f1edc7-970e-42fb-ba4e-cbfe0661b437" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.750195Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.748274Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.775850Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.773417Z&quot;}}" data-execution_count="9">
<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">comparison <span class="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-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">term =</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;">"age"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>),</span>
<span id="cb10-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">manual_beta =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(beta_manual),</span>
<span id="cb10-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coxph_beta =</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;">coef</span>(fit_cox)),</span>
<span id="cb10-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">manual_se =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(se_manual),</span>
<span id="cb10-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coxph_se =</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;">sqrt</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diag</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vcov</span>(fit_cox))))</span>
<span id="cb10-7">)</span>
<span id="cb10-8"></span>
<span id="cb10-9">comparison[, <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;">round</span>(comparison[, <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;">4</span>)</span>
<span id="cb10-10"></span>
<span id="cb10-11">comparison</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 2 × 5</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">term</th>
<th data-quarto-table-cell-role="th" scope="col">manual_beta</th>
<th data-quarto-table-cell-role="th" scope="col">coxph_beta</th>
<th data-quarto-table-cell-role="th" scope="col">manual_se</th>
<th data-quarto-table-cell-role="th" scope="col">coxph_se</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>age</td>
<td>0.0170</td>
<td>0.0170</td>
<td>0.0092</td>
<td>0.0092</td>
</tr>
<tr class="even">
<td>sex</td>
<td>-0.5126</td>
<td>-0.5126</td>
<td>0.1675</td>
<td>0.1675</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The manual and <code>coxph()</code> estimates should agree closely because both calculations now use the same partial likelihood and the same method for handling tied event times.</p>
<p>The fitted coefficients are expressed on the <strong>log-hazard scale</strong>. Exponentiating them gives the corresponding hazard ratios:</p>
<div id="325ee879-98e7-4fa1-b3f2-b88b1d70ef0b" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.780511Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.779016Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.800983Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.799014Z&quot;}}" data-execution_count="10">
<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"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(beta_manual)</span>
<span id="cb11-2"><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;">coef</span>(fit_cox))</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>age</dt><dd>1.01715863844201</dd><dt>sex</dt><dd>0.598955202302099</dd></dl>
</div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>age</dt><dd>1.01715843259764</dd><dt>sex</dt><dd>0.598957406233886</dd></dl>
</div>
</div>
<p>For age, the hazard ratio represents the multiplicative change in the hazard associated with a one-year increase in age, holding sex constant.</p>
<p>For sex, the hazard ratio compares females (<code>sex = 1</code>) with males (<code>sex = 0</code>), holding age constant. A hazard ratio below 1 indicates a lower estimated hazard for females than for males.</p>
<p>The manually estimated coefficients and standard errors agree with those returned by <code>coxph()</code> to several decimal places. Because both implementations use the Breslow method for tied event times, the very small remaining differences are due only to numerical optimization and floating-point precision.</p>
</section>
<section id="interpreting-the-cox-coefficients" class="level3" data-number="4.8">
<h3 data-number="4.8" class="anchored" data-anchor-id="interpreting-the-cox-coefficients"><span class="header-section-number">4.8</span> Interpreting the Cox Coefficients</h3>
<p>The coefficients produced by a Cox model are expressed on the <strong>log-hazard scale</strong>. Exponentiating a coefficient converts it into a hazard ratio:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cmathrm%7BHR%7D=%5Cexp(%5Cbeta).%0A"></p>
<p>A hazard ratio greater than 1 indicates a higher estimated hazard, while a hazard ratio below 1 indicates a lower estimated hazard, holding the other covariates fixed.</p>
<p>For age, the estimated coefficient is approximately</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%5Cbeta_%7B%5Ctext%7Bage%7D%7D=0.017.%0A"></p>
<p>Exponentiating gives</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cexp(0.017)%5Capprox1.017.%0A"></p>
<p>This means that each additional year of age is associated with an estimated <strong>1.7% increase in the instantaneous hazard of death</strong>, holding sex constant.</p>
<p>The effect appears small because the coefficient describes a one-year difference. Over a ten-year age difference, the corresponding hazard ratio is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cexp(10%5Ctimes0.017)%5Capprox1.19.%0A"></p>
<p>Thus, a patient who is ten years older has an estimated hazard approximately 19% higher, assuming the proportional hazards model is appropriate and the other covariates remain fixed.</p>
<p>For sex, coded as</p>
<ul>
<li><code>0 = male</code>,</li>
<li><code>1 = female</code>,</li>
</ul>
<p>the estimated coefficient is approximately</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%5Cbeta_%7B%5Ctext%7Bsex%7D%7D=-0.513.%0A"></p>
<p>The corresponding hazard ratio is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cexp(-0.513)%5Capprox0.60.%0A"></p>
<p>Therefore, female patients in this cohort have an estimated hazard of death approximately <strong>0.60 times that of male patients</strong>, after adjusting for age. Equivalently, this corresponds to an estimated <strong>40% lower hazard</strong>:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A1-0.60=0.40.%0A"></p>
<p>These interpretations describe associations within this dataset. They should not automatically be interpreted as causal effects.</p>
</section>
<section id="standard-errors-from-the-information-matrix" class="level3" data-number="4.9">
<h3 data-number="4.9" class="anchored" data-anchor-id="standard-errors-from-the-information-matrix"><span class="header-section-number">4.9</span> Standard Errors from the Information Matrix</h3>
<p>Estimating the coefficients is only part of the analysis. We also need to quantify their uncertainty.</p>
<p>Let</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cell_p(%5Cbeta)%0A"></p>
<p>denote the Cox log partial likelihood. The observed information matrix is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AI(%5Cbeta)%0A=-%5Cfrac%7B%5Cpartial%5E2%5Cell_p(%5Cbeta)%7D%0A%7B%5Cpartial%5Cbeta,%5Cpartial%5Cbeta%5ET%7D.%0A"></p>
<p>The estimated covariance matrix of the fitted coefficients is obtained by inverting the observed information matrix at the estimated parameter values:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cwidehat%7B%5Cmathrm%7BVar%7D%7D(%5Chat%5Cbeta)%0A=I(%5Chat%5Cbeta)%5E%7B-1%7D.%0A"></p>
<p>The standard error of each coefficient is then the square root of the corresponding diagonal element:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cmathrm%7BSE%7D(%5Chat%5Cbeta_j)%0A=%5Csqrt%7B%0A%5Cleft%5B%0AI(%5Chat%5Cbeta)%5E%7B-1%7D%0A%5Cright%5D_%7Bjj%7D%0A%7D.%0A"></p>
<p>In our implementation, <code>optim()</code> minimizes the <strong>negative log partial likelihood</strong>. Therefore, when <code>hessian = TRUE</code>, the returned Hessian is already the observed information matrix:</p>
<div id="77bcb3e7-fd5f-4555-8c5e-2ae1c20e21a5" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.806081Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.804106Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.821428Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.819394Z&quot;}}" data-execution_count="11">
<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">information_matrix <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fit_manual<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hessian</span>
<span id="cb12-2"></span>
<span id="cb12-3">covariance_matrix <span class="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>(information_matrix)</span>
<span id="cb12-4"></span>
<span id="cb12-5">se_manual <span class="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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diag</span>(covariance_matrix))</span></code></pre></div></div>
</div>
<p>This means the same optimization procedure provides both</p>
<ul>
<li>the coefficient estimates, through the location of the minimum, and</li>
<li>their estimated uncertainty, through the curvature of the objective function around that minimum.</li>
</ul>
<p>A sharply curved likelihood produces smaller standard errors and more precise coefficient estimates. A flatter likelihood produces larger standard errors, indicating greater uncertainty about the fitted effects.</p>
</section>
</section>
<section id="residual-diagnostics-in-the-cox-model" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="residual-diagnostics-in-the-cox-model"><span class="header-section-number">5</span> Residual Diagnostics in the Cox Model</h2>
<p>In ordinary linear regression, residuals are easy to define—they are simply the difference between the observed and predicted values of the response variable.</p>
<p>Survival analysis is different. Because many observations are <strong>censored</strong>, we often do not know the true event time for every individual. Consequently, there is no single “raw residual” analogous to that used in linear regression.</p>
<p>Instead, the Cox proportional hazards model uses several specialized residuals, each designed to answer a different diagnostic question. Among the most commonly used are:</p>
<ul>
<li><strong>Martingale residuals</strong>, used to assess model fit and detect nonlinearity in covariate effects.</li>
<li><strong>Deviance residuals</strong>, a transformation of martingale residuals that is more symmetric and useful for identifying outliers.</li>
<li><strong>Schoenfeld residuals</strong>, used to assess the proportional hazards assumption.</li>
<li><strong>Scaled Schoenfeld residuals</strong>, commonly used in formal tests of proportional hazards, such as the <code>cox.zph()</code> test in R.</li>
</ul>
<section id="martingale-residuals" class="level3" data-number="5.1">
<h3 data-number="5.1" class="anchored" data-anchor-id="martingale-residuals"><span class="header-section-number">5.1</span> Martingale Residuals</h3>
<p>The <strong>martingale residual</strong> compares what was actually observed with what the fitted Cox model expected for each individual.</p>
<p>It is defined as</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AM_i%0A=%5Cdelta_i%20%5Cwidehat%7BH%7D_0(t_i)%0A%5Cexp(%5Chat%5Cbeta%5ET%20X_i),%0A"></p>
<p>where</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?%5Cdelta_i"> is the event indicator (1 = event, 0 = censored),</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Cwidehat%7BH%7D_0(t_i)"> is the estimated <strong>baseline cumulative hazard</strong> evaluated at the observed follow-up time,</li>
<li><img src="https://latex.codecogs.com/png.latex?X_i"> is the individual’s covariate vector,</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta"> is the vector of estimated regression coefficients.</li>
</ul>
<p>The estimated baseline cumulative hazard is usually obtained using the <strong>Breslow estimator</strong>,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cwidehat%7BH%7D_0(t)%0A=%5Csum_%7Bt_j%5Cle%20t%7D%0A%5Cfrac%7Bd_j%7D%0A%7B%5Csum_%7Bl%5Cin%20R(t_j)%7D%0A%5Cexp(%5Chat%5Cbeta%5ET%20X_l)%7D,%0A"></p>
<p>where</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?d_j"> is the number of events at time <img src="https://latex.codecogs.com/png.latex?t_j">, and</li>
<li><img src="https://latex.codecogs.com/png.latex?R(t_j)"> is the risk set immediately before time <img src="https://latex.codecogs.com/png.latex?t_j">.</li>
</ul>
<p>Notice that the martingale residual is simply</p>
<blockquote class="blockquote">
<p><strong>Observed events − Expected cumulative hazard</strong></p>
</blockquote>
<p>making it conceptually similar to an observed-minus-expected residual used in many statistical models.</p>
</section>
<section id="interpreting-martingale-residuals" class="level3" data-number="5.2">
<h3 data-number="5.2" class="anchored" data-anchor-id="interpreting-martingale-residuals"><span class="header-section-number">5.2</span> Interpreting Martingale Residuals</h3>
<p>Martingale residuals have some unusual mathematical properties.</p>
<ul>
<li>They are <strong>bounded above by 1</strong>.</li>
<li>They are <strong>unbounded below</strong>.</li>
<li>Their distribution is often highly skewed.</li>
</ul>
<p>A positive residual indicates that fewer events were expected than observed for that individual.</p>
<p>A large negative residual indicates that the individual survived substantially longer than the model predicted based on their covariates.</p>
<p>Because of their asymmetry, martingale residuals are <strong>not ideal for identifying outliers directly</strong>. Instead, they are primarily used to assess whether the functional form of a continuous covariate is appropriate.</p>
<p>For example, after fitting a Cox model with age as a linear predictor, one can plot the martingale residuals against age. If the residuals exhibit a systematic curved pattern rather than random scatter, this suggests that the effect of age may not be linear and that a transformation or spline term could provide a better fit.</p>
<p>In R, martingale residuals can be obtained directly from a fitted Cox model using</p>
<div id="95523b0d-f711-47c7-8390-91e0092ea42d" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.826673Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.824987Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.838613Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.836383Z&quot;}}" data-execution_count="12">
<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">martingale_residuals <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">residuals</span>(fit_cox, <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;">"martingale"</span>)</span></code></pre></div></div>
</div>
<p>In the next section, we will examine <strong>Schoenfeld residuals</strong>, which play a different role: testing whether the proportional hazards assumption underlying the Cox model is satisfied.</p>
</section>
<section id="computing-martingale-residuals-by-hand" class="level3" data-number="5.3">
<h3 data-number="5.3" class="anchored" data-anchor-id="computing-martingale-residuals-by-hand"><span class="header-section-number">5.3</span> Computing Martingale Residuals by Hand</h3>
<p>We can reproduce the martingale residuals returned by <code>coxph()</code> by calculating the Breslow baseline cumulative hazard directly.</p>
<p>First, we extract the fitted coefficients and calculate each individual’s relative hazard:</p>
<div id="8fd1f3e2-8339-42fe-865f-0229bd2cc8b6" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.844259Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.842544Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.861107Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.859293Z&quot;}}" data-execution_count="13">
<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">beta_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;">coef</span>(fit_cox)</span>
<span id="cb14-2"></span>
<span id="cb14-3">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.matrix</span>(</span>
<span id="cb14-4">  lung2[, <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;">"age"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>)]</span>
<span id="cb14-5">)</span>
<span id="cb14-6"></span>
<span id="cb14-7">relative_hazard <span class="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.vector</span>(</span>
<span id="cb14-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(X <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> beta_hat)</span>
<span id="cb14-9">)</span></code></pre></div></div>
</div>
<p>Next, we estimate the baseline cumulative hazard using the Breslow estimator:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cwidehat%20H_0(t)%0A=%5Csum_%7Bt_j%5Cle%20t%7D%0A%5Cfrac%7Bd_j%7D%0A%7B%5Csum_%7Bl%5Cin%20R(t_j)%7D%0A%5Cexp(%5Chat%5Cbeta%5ET%20X_l)%7D.%0A"></p>
<div id="8114f165-1197-4b74-8b43-f92d4c3ceb79" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.866979Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.865575Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.896203Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.893581Z&quot;}}" data-execution_count="14">
<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;"># Distinct observed event times</span></span>
<span id="cb15-2">event_times <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sort</span>(</span>
<span id="cb15-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time[lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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="cb15-4">)</span>
<span id="cb15-5"></span>
<span id="cb15-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Breslow baseline cumulative hazard</span></span>
<span id="cb15-7">H0 <span class="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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(event_times))</span>
<span id="cb15-8">cumulative_hazard <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>
<span id="cb15-9"></span>
<span id="cb15-10"><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>(event_times)) {</span>
<span id="cb15-11"></span>
<span id="cb15-12">  tj <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> event_times[j]</span>
<span id="cb15-13"></span>
<span id="cb15-14">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of events at tj</span></span>
<span id="cb15-15">  d_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;">sum</span>(</span>
<span id="cb15-16">    lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> tj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span></span>
<span id="cb15-17">    lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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="cb15-18">  )</span>
<span id="cb15-19"></span>
<span id="cb15-20">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Individuals in the risk set at tj</span></span>
<span id="cb15-21">  risk_set <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> tj</span>
<span id="cb15-22"></span>
<span id="cb15-23">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Breslow increment</span></span>
<span id="cb15-24">  hazard_increment <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb15-25">    d_j <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>(relative_hazard[risk_set])</span>
<span id="cb15-26"></span>
<span id="cb15-27">  cumulative_hazard <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb15-28">    cumulative_hazard <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> hazard_increment</span>
<span id="cb15-29"></span>
<span id="cb15-30">  H0[j] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cumulative_hazard</span>
<span id="cb15-31">}</span></code></pre></div></div>
</div>
<p>The cumulative baseline hazard is a step function. For each individual, we therefore need the value corresponding to the most recent event time at or before their observed follow-up time.</p>
<p>Before the first event, the cumulative hazard must equal zero.</p>
<div id="247e7dee-8ff5-4b8c-82c5-176cd9e54336" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.901729Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.899796Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.917240Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.914854Z&quot;}}" data-execution_count="15">
<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;"># Locate the final event time at or before each observed time</span></span>
<span id="cb16-2">interval_index <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">findInterval</span>(</span>
<span id="cb16-3">  lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time,</span>
<span id="cb16-4">  event_times</span>
<span id="cb16-5">)</span>
<span id="cb16-6"></span>
<span id="cb16-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Evaluate H0(t) at each individual's observed follow-up time</span></span>
<span id="cb16-8">H0_at_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;">ifelse</span>(</span>
<span id="cb16-9">  interval_index <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="cb16-10">  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb16-11">  H0[interval_index]</span>
<span id="cb16-12">)</span>
<span id="cb16-13"></span>
<span id="cb16-14"></span></code></pre></div></div>
</div>
<p>The expected cumulative number of events for individual (i) is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cwidehat%20H_0(Y_i)%0A%5Cexp(%5Chat%5Cbeta%5ET%20X_i).%0A"></p>
<p>The martingale residual is therefore</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AM_i%0A=%5Cdelta_i%20%5Cwidehat%20H_0(Y_i)%0A%5Cexp(%5Chat%5Cbeta%5ET%20X_i).%0A"></p>
<div id="9278344d-632f-4356-bc76-4a599d9f5a0d" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.922924Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.920691Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.933726Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.931784Z&quot;}}" data-execution_count="16">
<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">martingale_manual <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb17-2">  lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span></span>
<span id="cb17-3">  H0_at_Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> relative_hazard</span></code></pre></div></div>
</div>
<p>We can compare the manual calculation with the residuals returned by <code>coxph()</code>:</p>
<div id="6d6df668-0fce-4ee8-ae7b-381951777553" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:24.938691Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:24.937013Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:24.996880Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:24.963001Z&quot;}}" data-execution_count="17">
<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">martingale_coxph <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">residuals</span>(</span>
<span id="cb18-2">  fit_cox,</span>
<span id="cb18-3">  <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;">"martingale"</span></span>
<span id="cb18-4">)</span>
<span id="cb18-5"></span>
<span id="cb18-6">comparison <span class="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="cb18-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">manual =</span> martingale_manual,</span>
<span id="cb18-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coxph =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(martingale_coxph),</span>
<span id="cb18-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">difference =</span> martingale_manual <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;">as.numeric</span>(martingale_coxph)</span>
<span id="cb18-11">)</span>
<span id="cb18-12"></span>
<span id="cb18-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(</span>
<span id="cb18-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transform</span>(</span>
<span id="cb18-15">    comparison,</span>
<span id="cb18-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">manual =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(manual, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb18-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coxph =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(coxph, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb18-18">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">difference =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(difference, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span>
<span id="cb18-19">  )</span>
<span id="cb18-20">)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 3</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">manual</th>
<th data-quarto-table-cell-role="th" scope="col">coxph</th>
<th data-quarto-table-cell-role="th" scope="col">difference</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>0.0062</td>
<td>0.0062</td>
<td>0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>-0.5030</td>
<td>-0.5030</td>
<td>0</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>-3.1272</td>
<td>-3.1272</td>
<td>0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>0.5335</td>
<td>0.5335</td>
<td>0</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>-2.3474</td>
<td>-2.3474</td>
<td>0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>-4.2477</td>
<td>-4.2477</td>
<td>0</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The two sets of residuals should agree to numerical precision, provided that <code>fit_cox</code> was fitted using the Breslow method:</p>
</section>
<section id="schoenfeld-residuals" class="level3" data-number="5.4">
<h3 data-number="5.4" class="anchored" data-anchor-id="schoenfeld-residuals"><span class="header-section-number">5.4</span> Schoenfeld Residuals</h3>
<p>Whereas martingale residuals assess the fit of individual observations, <strong>Schoenfeld residuals</strong> are used to assess the <strong>proportional hazards assumption</strong>. At each observed event time (t_j), the Schoenfeld residual is defined as the difference between the covariate value of the individual who experienced the event and the risk-set-weighted average covariate value:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ar_j%20=%20X_%7Bi_j%7D%20-%20%5Cbar%20X(%5Chat%5Cbeta,%20t_j),%20%5Cqquad%0A%5Cbar%20X(%5Chat%5Cbeta,%20t_j)%0A=%5Cfrac%7B%5Csum_%7Bl%20%5Cin%20R(t_j)%7D%20X_l%20%5Cexp(%5Chat%5Cbeta%5ET%20X_l)%7D%0A%7B%5Csum_%7Bl%20%5Cin%20R(t_j)%7D%20%5Cexp(%5Chat%5Cbeta%5ET%20X_l)%7D.%0A"></p>
<p>There is <strong>one Schoenfeld residual for each event and each covariate</strong>, rather than one residual per individual. If the proportional hazards assumption holds, these residuals should show <strong>no systematic trend</strong> when plotted against time.</p>
</section>
<section id="computing-schoenfeld-residuals-in-r" class="level3" data-number="5.5">
<h3 data-number="5.5" class="anchored" data-anchor-id="computing-schoenfeld-residuals-in-r"><span class="header-section-number">5.5</span> Computing Schoenfeld Residuals in R</h3>
<p>The <code>survival</code> package computes Schoenfeld residuals directly from a fitted Cox model. The residual matrix has <strong>one row for each observed event</strong> and <strong>one column for each covariate</strong>.</p>
<div id="f6054434-bd6d-4032-9ddb-c27b8c8f2628" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.003113Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.001410Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.037873Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.035604Z&quot;}}" data-execution_count="18">
<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"></span>
<span id="cb19-2">sch <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">residuals</span>(fit_cox, <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;">"schoenfeld"</span>)</span>
<span id="cb19-3"></span>
<span id="cb19-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(sch)</span>
<span id="cb19-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(sch)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<style>
.list-inline {list-style: none; margin:0; padding: 0}
.list-inline>li {display: inline-block}
.list-inline>li:not(:last-child)::after {content: "\00b7"; padding: 0 .5ex}
</style>
<ol class="list-inline"><li>165</li><li>2</li></ol>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 6 × 2 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">age</th>
<th data-quarto-table-cell-role="th" scope="col">sex</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>0.9382653</td>
<td>0.7269349</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">11</th>
<td>9.9412847</td>
<td>-0.2707258</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">11</th>
<td>16.9412847</td>
<td>-0.2707258</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">11</th>
<td>2.9412847</td>
<td>-0.2707258</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">12</th>
<td>10.1431920</td>
<td>-0.2759338</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">13</th>
<td>12.2083432</td>
<td>-0.2777061</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>In practice, the proportional hazards assumption is usually assessed by plotting the <strong>scaled Schoenfeld residuals</strong> against event time and testing whether their slope differs significantly from zero. In R, the <code>cox.zph()</code> function performs both the graphical diagnostic and the corresponding statistical test.</p>
<p>Deviance residuals, Cox–Snell residuals, and DFBETAs are additional diagnostic measures derived from the same martingale and score-function framework. They are useful for identifying outliers, assessing overall model fit, and evaluating influential observations, and are beyond the scope of this tutorial.</p>
</section>
<section id="comparing-survival-between-groups" class="level3" data-number="5.6">
<h3 data-number="5.6" class="anchored" data-anchor-id="comparing-survival-between-groups"><span class="header-section-number">5.6</span> Comparing Survival Between Groups</h3>
<p>Before performing the log-rank test, the group-specific Kaplan–Meier curves provide a visual summary of the survival difference.</p>
<div id="8cfbecc9-f013-47d8-9cf3-23ccaba8274c" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.043139Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.041338Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.162879Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.160550Z&quot;}}" data-execution_count="19">
<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>
<span id="cb20-2"></span>
<span id="cb20-3">km_sex <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">survfit</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Surv</span>(time, status) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> sex, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> lung2)</span>
<span id="cb20-4"></span>
<span id="cb20-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb20-6">  km_sex,</span>
<span id="cb20-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Time"</span>,</span>
<span id="cb20-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Estimated survival probability"</span>,</span>
<span id="cb20-9">  <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;">"Kaplan–Meier Curves by Sex"</span>,</span>
<span id="cb20-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mark.time =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb20-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lwd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb20-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</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;">"steelblue"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"firebrick"</span>)</span>
<span id="cb20-13">)</span>
<span id="cb20-14"></span>
<span id="cb20-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">legend</span>(</span>
<span id="cb20-16">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottomleft"</span>,</span>
<span id="cb20-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend =</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;">"Male"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Female"</span>),</span>
<span id="cb20-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</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;">"steelblue"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"firebrick"</span>),</span>
<span id="cb20-19">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lwd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb20-20">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bty =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n"</span></span>
<span id="cb20-21">)</span>
<span id="cb20-22"></span>
<span id="cb20-23"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/survival_analysis/survival-analysis-tutorial_files/figure-html/cell-20-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The separation between the curves gives an immediate visual impression of the group difference, while the log-rank test formally evaluates whether the survival experiences differ over follow-up.</p>
</section>
</section>
<section id="the-log-rank-test" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="the-log-rank-test"><span class="header-section-number">6</span> The Log-Rank Test</h2>
<p>The <strong>log-rank test</strong> is the most widely used statistical test for comparing survival curves between two or more groups. Unlike the Cox proportional hazards model, it does <strong>not</strong> estimate regression coefficients or require covariates. Instead, it tests the null hypothesis that the groups have the same underlying survival experience.</p>
<p>At each observed event time, the test compares the <strong>observed</strong> number of events in each group with the <strong>expected</strong> number of events under the null hypothesis of equal survival.</p>
<p>Mathematically,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AO_1%20-%20E_1%0A=%5Csum_%7Bj=1%7D%5E%7Bk%7D%0A%5Cleft(%0Ad_%7B1j%7D%0A-%5Cfrac%7Bn_%7B1j%7D%7D%7Bn_j%7Dd_j%0A%5Cright),%0A"></p>
<p>where</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?d_%7B1j%7D"> is the number of observed events in Group 1 at event time <img src="https://latex.codecogs.com/png.latex?t_j">,</li>
<li><img src="https://latex.codecogs.com/png.latex?n_%7B1j%7D"> is the number of individuals at risk in Group 1 just before <img src="https://latex.codecogs.com/png.latex?t_j">,</li>
<li><img src="https://latex.codecogs.com/png.latex?d_j"> is the total number of events at <img src="https://latex.codecogs.com/png.latex?t_j">,</li>
<li><img src="https://latex.codecogs.com/png.latex?n_j"> is the total number of individuals at risk at <img src="https://latex.codecogs.com/png.latex?t_j">.</li>
</ul>
<p>The variance of the observed-minus-expected statistic is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cmathrm%7BVar%7D(O_1-E_1)%0A=%5Csum_%7Bj=1%7D%5E%7Bk%7D%0A%5Cfrac%7B%0An_%7B1j%7Dn_%7B2j%7D%5C,%0Ad_j(n_j-d_j)%0A%7D%7B%0An_j%5E2(n_j-1)%0A%7D.%0A"></p>
<p>The log-rank test statistic is then</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AZ%5E2%0A=%0A%5Cfrac%7B(O_1-E_1)%5E2%7D%0A%7B%5Cmathrm%7BVar%7D(O_1-E_1)%7D,%0A"></p>
<p>which follows approximately a chi-squared distribution with one degree of freedom under the null hypothesis.</p>
<blockquote class="blockquote">
<p><strong>Why does this look familiar?</strong></p>
<p>The log-rank test is built from exactly the same <strong>risk-set bookkeeping</strong> used by the Kaplan–Meier estimator. At each event time, we count how many individuals remain at risk (<img src="https://latex.codecogs.com/png.latex?n_j">) and how many events occur (<img src="https://latex.codecogs.com/png.latex?d_j">). The only difference is that the log-rank test performs these calculations separately for each group and compares the observed and expected numbers of events over the entire follow-up period.</p>
</blockquote>
<section id="implementing-the-log-rank-test-by-hand" class="level3" data-number="6.1">
<h3 data-number="6.1" class="anchored" data-anchor-id="implementing-the-log-rank-test-by-hand"><span class="header-section-number">6.1</span> Implementing the Log-Rank Test by Hand</h3>
<p>To illustrate the calculation, we divide the <code>lung</code> dataset into two groups using the median age:</p>
<ul>
<li><code>old</code>: age above the median,</li>
<li><code>young</code>: age at or below the median.</li>
</ul>
<p>At each observed event time, the code calculates the numbers at risk and the observed events in the older group, then accumulates the observed count, expected count, and variance across follow-up.</p>
<div id="0886af4f-38ff-4da6-92ad-82df50dda719" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.168633Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.166825Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.224922Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.222412Z&quot;}}" data-execution_count="20">
<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>
<span id="cb21-2">lung3 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>(lung[, <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;">"time"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"age"</span>)])</span>
<span id="cb21-3"></span>
<span id="cb21-4">lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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="cb21-5">lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>agegrp <span class="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>
<span id="cb21-6">  lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>age <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;">median</span>(lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>age),</span>
<span id="cb21-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"old"</span>,</span>
<span id="cb21-8">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"young"</span></span>
<span id="cb21-9">)</span>
<span id="cb21-10"></span>
<span id="cb21-11">event_times <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sort</span>(</span>
<span id="cb21-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time[lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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="cb21-13">)</span>
<span id="cb21-14"></span>
<span id="cb21-15">O1 <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>
<span id="cb21-16">E1 <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>
<span id="cb21-17">V  <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>
<span id="cb21-18"></span>
<span id="cb21-19"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (tj <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> event_times) {</span>
<span id="cb21-20"></span>
<span id="cb21-21">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Individuals at risk immediately before tj</span></span>
<span id="cb21-22">  risk_idx <span class="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>(lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> tj)</span>
<span id="cb21-23"></span>
<span id="cb21-24">  n_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;">length</span>(risk_idx)</span>
<span id="cb21-25">  n1j  <span class="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>(lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>agegrp[risk_idx] <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;">"old"</span>)</span>
<span id="cb21-26">  n2j  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n1j</span>
<span id="cb21-27"></span>
<span id="cb21-28">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Total events and events in the older group at tj</span></span>
<span id="cb21-29">  d_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;">sum</span>(</span>
<span id="cb21-30">    lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> tj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span></span>
<span id="cb21-31">    lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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="cb21-32">  )</span>
<span id="cb21-33"></span>
<span id="cb21-34">  d1j <span class="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>
<span id="cb21-35">    lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> tj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span></span>
<span id="cb21-36">    lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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;</span></span>
<span id="cb21-37">    lung3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>agegrp <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;">"old"</span></span>
<span id="cb21-38">  )</span>
<span id="cb21-39"></span>
<span id="cb21-40">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Accumulate observed and expected events</span></span>
<span id="cb21-41">  O1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> O1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> d1j</span>
<span id="cb21-42">  E1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> E1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (n1j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_j) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> d_j</span>
<span id="cb21-43"></span>
<span id="cb21-44">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Accumulate the variance</span></span>
<span id="cb21-45">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (n_j <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;">1</span>) {</span>
<span id="cb21-46">    V <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> V <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb21-47">      (n1j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n2j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> d_j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (n_j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> d_j)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span></span>
<span id="cb21-48">      (n_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;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (n_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="cb21-49">  }</span>
<span id="cb21-50">}</span>
<span id="cb21-51"></span>
<span id="cb21-52">Z2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (O1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> E1)<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> V</span>
<span id="cb21-53"></span>
<span id="cb21-54"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb21-55">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">O1 =</span> O1,</span>
<span id="cb21-56">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">E1 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(E1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb21-57">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Var =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(V, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb21-58">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Z2 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(Z2, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb21-59">)</span>
<span id="cb21-60"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>O1</dt><dd>85</dd><dt>E1</dt><dd>76.237</dd><dt>Var</dt><dd>40.821</dd><dt>Z2</dt><dd>1.881</dd></dl>
</div>
</div>
<p>Here, (O_1) is the total number of observed events in the older group, (E_1) is the number expected under equal survival, and (Z^2) is the log-rank chi-squared statistic.</p>
<p>We can compare the manual result with R’s <code>survdiff()</code> function:</p>
<div id="a3376dcc" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.230845Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.228623Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.260018Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.257668Z&quot;}}" data-execution_count="21">
<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>
<span id="cb22-2"></span>
<span id="cb22-3"></span>
<span id="cb22-4"></span>
<span id="cb22-5">fit_logrank <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">survdiff</span>(</span>
<span id="cb22-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Surv</span>(time, status) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> agegrp,</span>
<span id="cb22-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> lung3</span>
<span id="cb22-8">)</span>
<span id="cb22-9"></span>
<span id="cb22-10">fit_logrank</span>
<span id="cb22-11"></span>
<span id="cb22-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb22-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">manual_Z2 =</span> Z2,</span>
<span id="cb22-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">survdiff_Z2 =</span> fit_logrank<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>chisq</span>
<span id="cb22-15">)</span>
<span id="cb22-16"></span>
<span id="cb22-17"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>Call:
survdiff(formula = Surv(time, status) ~ agegrp, data = lung3)

               N Observed Expected (O-E)^2/E (O-E)^2/V
agegrp=old   111       85     76.2     1.007      1.88
agegrp=young 117       80     88.8     0.865      1.88

 Chisq= 1.9  on 1 degrees of freedom, p= 0.2 </code></pre>
</div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>manual_Z2</dt><dd>1.88099912472048</dd><dt>survdiff_Z2</dt><dd>1.88099912472049</dd></dl>
</div>
</div>
<p>The two chi-squared statistics should agree to numerical precision.</p>
</section>
</section>
<section id="a-full-proportional-hazards-diagnostic-workflow" class="level2" data-number="7">
<h2 data-number="7" class="anchored" data-anchor-id="a-full-proportional-hazards-diagnostic-workflow"><span class="header-section-number">7</span> A Full Proportional-Hazards Diagnostic Workflow</h2>
<p>The residuals introduced above are the raw material. Used together, in a fixed order, they form a standard diagnostic workflow for a fitted Cox model: does the model fit at all (Cox–Snell), are there poorly-fit or influential individuals (deviance), and does the proportional hazards assumption actually hold (<code>cox.zph</code>).</p>
<section id="deviance-residuals" class="level3" data-number="7.1">
<h3 data-number="7.1" class="anchored" data-anchor-id="deviance-residuals"><span class="header-section-number">7.1</span> Deviance residuals</h3>
<p>Martingale residuals are useful but skewed: they range over <img src="https://latex.codecogs.com/png.latex?(-%5Cinfty,%201%5D">, so a handful of extreme negative values can dominate a plot. Deviance residuals are a variance-stabilizing transform of the martingale residual <img src="https://latex.codecogs.com/png.latex?M_i">:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AD_i%20=%20%5Ctext%7Bsign%7D(M_i)%5Csqrt%7B-2%5Cleft%5BM_i%20+%20%5Cdelta_i%20%5Clog(%5Cdelta_i%20-%20M_i)%5Cright%5D%7D.%0A"></p>
<blockquote class="blockquote">
<p><strong>Why bother transforming at all?</strong> <img src="https://latex.codecogs.com/png.latex?D_i"> is approximately symmetric around 0 for a well-fitting model, the way ordinary residuals are in linear regression. That makes them far more useful than martingale residuals for spotting individual outliers by eye.</p>
</blockquote>
<div id="c4e4f81e" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.265335Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.263484Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.290202Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.287819Z&quot;}}" data-execution_count="22">
<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">dev_manual <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sign</span>(martingale_manual) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb24-2">  <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;">pmax</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;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (martingale_manual <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <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>(lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> martingale_manual))))</span>
<span id="cb24-3">dev_coxph <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">residuals</span>(fit_cox, <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;">"deviance"</span>)</span>
<span id="cb24-4"></span>
<span id="cb24-5"><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;">head</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;">manual =</span> dev_manual, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coxph =</span> dev_coxph)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 6 × 2 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">manual</th>
<th data-quarto-table-cell-role="th" scope="col">coxph</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>0.0062</td>
<td>0.0062</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>-0.4371</td>
<td>-0.4371</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>-2.5009</td>
<td>-2.5009</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>0.6767</td>
<td>0.6767</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>-1.5095</td>
<td>-1.5095</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>-2.9147</td>
<td>-2.9147</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The manually computed deviance residuals match those returned by <code>coxph()</code>. Plotting deviance residuals against the linear predictor (= X) is a standard diagnostic for identifying potential outliers and assessing model fit.</p>
<p>Plotting the deviance residuals against the fitted linear predictor provides a simple visual check for unusual observations or systematic departures from the fitted Cox model.</p>
<div id="f974babe" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.295722Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.293596Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.401231Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.398199Z&quot;}}" data-execution_count="23">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb25-1"></span>
<span id="cb25-2">lp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(fit_cox, <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;">"lp"</span>)</span>
<span id="cb25-3"></span>
<span id="cb25-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb25-5">  lp,</span>
<span id="cb25-6">  dev_coxph,</span>
<span id="cb25-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>,</span>
<span id="cb25-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">adjustcolor</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"steelblue"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>),</span>
<span id="cb25-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Linear predictor"</span>,</span>
<span id="cb25-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Deviance residual"</span>,</span>
<span id="cb25-11">  <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;">"Deviance Residuals vs Linear Predictor"</span></span>
<span id="cb25-12">)</span>
<span id="cb25-13"></span>
<span id="cb25-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">h =</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;">lty =</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;">col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey40"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/survival_analysis/survival-analysis-tutorial_files/figure-html/cell-24-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>As you can see, the residuals are scattered roughly symmetrically around zero, with no obvious trend or a small number of extreme outlying observations.</p>
<p>No individual sits far outside the band formed by the rest, and there is no visible curvature — no sign that a transformation of <code>age</code> or <code>sex</code> is needed.</p>
</section>
<section id="coxsnell-residuals" class="level3" data-number="7.2">
<h3 data-number="7.2" class="anchored" data-anchor-id="coxsnell-residuals"><span class="header-section-number">7.2</span> Cox–Snell residuals</h3>
<p>Cox–Snell residuals check overall model fit rather than individual fit. For a correctly specified model, the residual</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AR_i%20=%20%5Chat%20H_0(Y_i)%5Cexp(%5Chat%5Cbeta%5ET%20X_i)%0A"></p>
<p>should behave like a censored sample from an <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BExponential%7D(1)"> distribution — because <img src="https://latex.codecogs.com/png.latex?R_i"> is just <img src="https://latex.codecogs.com/png.latex?%5Chat%5CLambda_i(Y_i)">, and the cumulative hazard of any survival time evaluated at itself is exponential with rate 1.</p>
<blockquote class="blockquote">
<p><strong>How is that checked in practice?</strong> Treat <img src="https://latex.codecogs.com/png.latex?%5C%7BR_i,%20%5Cdelta_i%5C%7D"> as a new survival dataset and estimate its own Kaplan–Meier cumulative hazard, <img src="https://latex.codecogs.com/png.latex?-%5Clog%20%5Chat%20S_R(r)">. If the original model fits well, this cumulative hazard should trace the 45° line <img src="https://latex.codecogs.com/png.latex?y%20=%20r">, since that is the cumulative hazard of a unit-rate exponential.</p>
</blockquote>
<p>Conveniently, <img src="https://latex.codecogs.com/png.latex?R_i%20=%20%5Cdelta_i%20-%20M_i">, so no separate calculation is needed beyond the martingale residuals already computed.</p>
<div id="067b20fa" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.407621Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.405773Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.486240Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.483877Z&quot;}}" data-execution_count="24">
<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">coxsnell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> martingale_manual   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># R_i = delta_i - M_i</span></span>
<span id="cb26-2">cs_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;">survfit</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Surv</span>(coxsnell, lung2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>status) <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="cb26-3"></span>
<span id="cb26-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(cs_fit<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>time, <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>(cs_fit<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>surv), <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;">"s"</span>,</span>
<span id="cb26-5">     <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cox-Snell residual"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Estimated cumulative hazard"</span>,</span>
<span id="cb26-6">     <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;">"Cox-Snell Residual Plot"</span>)</span>
<span id="cb26-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abline</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;">col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/survival_analysis/survival-analysis-tutorial_files/figure-html/cell-25-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The step function tracks the reference line closely apart from some flattening in the right tail, where only a handful of individuals remain at risk and the empirical cumulative hazard becomes noisy by construction. This is the expected pattern for an adequately fitting Cox model, rather than evidence of poor fit.</p>
</section>
<section id="testing-proportional-hazards-with-cox.zph" class="level3" data-number="7.3">
<h3 data-number="7.3" class="anchored" data-anchor-id="testing-proportional-hazards-with-cox.zph"><span class="header-section-number">7.3</span> Testing Proportional Hazards with <code>cox.zph()</code></h3>
<p>Schoenfeld residuals were introduced earlier as raw per-event quantities. <code>cox.zph()</code> turns them into a formal test by examining whether the <strong>scaled Schoenfeld residuals</strong> vary systematically with a transformation of event time. By default, it uses a Kaplan–Meier transformation of time and tests whether the estimated time-dependent trend is zero.</p>
<blockquote class="blockquote">
<p><strong>What does a significant result mean?</strong></p>
<p>A small p-value for a covariate indicates that its estimated effect on the hazard changes over follow-up time. In other words, the proportional hazards assumption may be violated for that covariate. The <code>GLOBAL</code> test evaluates the proportional hazards assumption for all covariates jointly.</p>
</blockquote>
<div id="745d6cc1" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.491837Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.489693Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.512769Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.510328Z&quot;}}" data-execution_count="25">
<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">zph_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;">cox.zph</span>(fit_cox)</span>
<span id="cb27-2">zph_fit</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>       chisq df    p
age    0.208  1 0.65
sex    2.599  1 0.11
GLOBAL 2.761  2 0.25</code></pre>
</div>
</div>
<div id="42ea8186" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:59:25.517961Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:59:25.516149Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:59:25.618442Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:59:25.614627Z&quot;}}" data-execution_count="26">
<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;">par</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mfrow =</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>
<span id="cb29-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(zph_fit)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/survival_analysis/survival-analysis-tutorial_files/figure-html/cell-27-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Neither covariate shows evidence of a violation of the proportional hazards assumption (age: (p = 0.65); sex: (p = 0.11); global test: (p = 0.25)). In both panels, the smoothed curves remain approximately horizontal and fluctuate around zero throughout follow-up. The proportional hazards assumption therefore appears reasonable for this model, and the estimated hazard ratios can be interpreted as approximately constant over the observed follow-up period.</p>
</section>
<section id="putting-the-workflow-together" class="level3" data-number="7.4">
<h3 data-number="7.4" class="anchored" data-anchor-id="putting-the-workflow-together"><span class="header-section-number">7.4</span> Putting the workflow together</h3>
<p>For a fitted Cox model, the same three checks apply in the same order every time:</p>
<ol type="1">
<li><strong>Cox–Snell residuals</strong> — does the model fit overall? Compare their cumulative hazard to the 45° line.</li>
<li><strong>Deviance residuals</strong> — which individuals fit badly? Plot against the linear predictor and scan for outliers or curvature.</li>
<li><strong><code>cox.zph()</code></strong> — does proportional hazards hold, covariate by covariate? A significant result flags exactly which covariate needs a time-varying effect or stratification.</li>
</ol>
</section>
</section>
<section id="summary" class="level2" data-number="8">
<h2 data-number="8" class="anchored" data-anchor-id="summary"><span class="header-section-number">8</span> Summary</h2>
<p>Kaplan–Meier estimation and Cox proportional hazards regression are built on the same counting-process framework but estimate different quantities.</p>
<ul>
<li><p><strong>Kaplan–Meier</strong> estimates the survival function (S(t)) directly as a product of conditional survival probabilities at each observed event time, with Greenwood’s formula providing its standard error.</p></li>
<li><p><strong>Cox proportional hazards regression</strong> models the hazard as [ h(t X)=h_0(t)(^T X), ] and estimates () by maximizing the partial likelihood, which eliminates the unspecified baseline hazard by conditioning on the risk set at each event time.</p></li>
</ul>
<p>On top of the fitted Cox model, a complete diagnostic workflow was developed from three residual types:</p>
<ul>
<li><p><strong>Cox–Snell residuals</strong> assess overall model fit by comparing the estimated cumulative hazard with the 45° reference line.</p></li>
<li><p><strong>Deviance residuals</strong> identify potential outliers and departures from the assumed functional form of the covariates.</p></li>
<li><p><strong><code>cox.zph()</code></strong>, based on scaled Schoenfeld residuals, formally tests the proportional hazards assumption for each covariate and for the model as a whole.</p></li>
</ul>
<p>Every quantity derived in this tutorial—including the Kaplan–Meier estimator (S(t)), its standard error, the Cox regression coefficients (), their standard errors, martingale, deviance, and Cox–Snell residuals, and the log-rank test statistic—was implemented directly from its mathematical definition in base R and verified against the corresponding functions in the <strong>survival</strong> package (<code>survfit()</code>, <code>coxph()</code>, <code>survdiff()</code>, and <code>cox.zph()</code>), with agreement to at least three decimal places throughout.</p>
</section>
<section id="references" class="level2" data-number="9">
<h2 data-number="9" class="anchored" data-anchor-id="references"><span class="header-section-number">9</span> References</h2>
<ol type="1">
<li><p>Kaplan EL, Meier P. <em>Nonparametric Estimation from Incomplete Observations</em>. Journal of the American Statistical Association. 1958;53(282):457–481. https://www.jstor.org/stable/2281868</p></li>
<li><p>Cox DR. <em>Regression Models and Life-Tables</em>. Journal of the Royal Statistical Society: Series B. 1972;34(2):187–220. https://www.jstor.org/stable/2985181</p></li>
<li><p>Therneau TM, Grambsch PM. <em>Modeling Survival Data: Extending the Cox Model</em>. Springer; 2000. https://link.springer.com/book/10.1007/978-1-4757-3294-8</p></li>
</ol>


</section>

 ]]></description>
  <category>Statistical Genetics</category>
  <category>Survival Analysis</category>
  <category>Biostatistics</category>
  <category>R</category>
  <guid>https://bntechie.github.io/tutorials/survival_analysis/survival-analysis-tutorial.html</guid>
  <pubDate>Sat, 25 Jul 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/survival_analysis/images/survival-curves.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Phylogenetic Generalized Least Squares (PGLS)</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/pgls/pgls_tutorial.html</link>
  <description><![CDATA[ 




<section id="the-problem-ordinary-regression-ignores" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="the-problem-ordinary-regression-ignores"><span class="header-section-number">1</span> The problem ordinary regression ignores</h2>
<p>Suppose you want to test whether brain size scales with body size across mammals, or whether flower color predicts pollinator visitation across plant species. The natural instinct is to collect one data point per species and run an ordinary least squares (OLS) regression. This is wrong, and has been known to be wrong since Felsenstein’s foundational 1985 paper.</p>
<p>The reason is simple. Species are not independent samples from some population; they are the tips of a phylogenetic tree. Two closely related species — say, a chimpanzee and a bonobo — resemble each other not because of some causal relationship between the traits under study, but because they inherited both traits from a recent common ancestor. Standard regression assumes residuals are independently and identically distributed. When your data points are structured by a phylogeny, that assumption is violated, and violated systematically: closely related species will tend to have correlated residuals. The practical consequence is that OLS understates its own uncertainty. Effective sample size is smaller than the number of species you counted, degrees of freedom are inflated, and p-values are optimistic — sometimes dramatically so (Felsenstein 1985; Freckleton et al.&nbsp;2002).</p>
<p>Phylogenetic Generalized Least Squares (PGLS) addresses this directly. Rather than discarding the phylogeny or trying to “correct for” it after the fact, PGLS builds the expected pattern of non-independence into the regression itself, as a covariance structure on the residuals.</p>
</section>
<section id="from-independent-contrasts-to-pgls" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="from-independent-contrasts-to-pgls"><span class="header-section-number">2</span> From independent contrasts to PGLS</h2>
<p>Felsenstein’s original solution was phylogenetically independent contrasts (PICs): transform the raw trait values into a set of statistically independent contrasts computed along the branches of the tree, then run a standard regression on the contrasts, forced through the origin (Felsenstein 1985). This works well but is somewhat inflexible — it handles only Brownian motion evolution, offers no natural way to include multiple predictors or categorical covariates, and doesn’t extend cleanly to generalized linear models.</p>
<p>Grafen (1989) reframed the problem as one of generalized least squares regression, showing that PICs are mathematically equivalent to a GLS fit in which the residual covariance matrix is derived from the tree. Martins and Hansen (1997) generalized this further, and Pagel (1997, 1999) introduced scaling parameters — most importantly λ (lambda) — that let the strength of the phylogenetic signal in the residuals be estimated from the data rather than assumed. Freckleton, Harvey, and Pagel (2002) demonstrated that this λ-based approach is robust and statistically powerful even when the phylogeny is incompletely known. This is the method now generally called PGLS, and it is the standard tool in modern phylogenetic comparative biology (Symonds and Blomberg 2014).</p>
</section>
<section id="the-model-formally" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="the-model-formally"><span class="header-section-number">3</span> The model, formally</h2>
<p>An ordinary least squares regression assumes</p>
<p><img src="https://latex.codecogs.com/png.latex?y%20=%20X%5Cbeta%20+%20%5Cvarepsilon,%20%5Cquad%20%5Cvarepsilon%20%5Csim%20N(0,%20%5Csigma%5E2%20I)"></p>
<p>that is, residuals are independent and identically distributed with covariance matrix <img src="https://latex.codecogs.com/png.latex?%5Csigma%5E2%20I">. PGLS replaces this with</p>
<p><img src="https://latex.codecogs.com/png.latex?y%20=%20X%5Cbeta%20+%20%5Cvarepsilon,%20%5Cquad%20%5Cvarepsilon%20%5Csim%20N(0,%20%5Csigma%5E2%20V)"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?V"> is an <img src="https://latex.codecogs.com/png.latex?n%20%5Ctimes%20n"> matrix encoding the expected covariance between species’ residuals, derived from the phylogeny. Under a Brownian motion model of evolution, the covariance between two species is proportional to the amount of shared branch length between them and the root: closely related species (which share a longer path from the root) get a higher covariance, tips connected only near the root get a lower one. The generalized least squares estimator is then</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Chat%7B%5Cbeta%7D%20=%20(X%5E%5Ctop%20V%5E%7B-1%7D%20X)%5E%7B-1%7D%20X%5E%5Ctop%20V%5E%7B-1%7D%20y"></p>
<p>which is just OLS after “whitening” the data by the inverse of the phylogenetic covariance structure. In practice, <img src="https://latex.codecogs.com/png.latex?V"> is rarely used raw; it is common to allow it to be scaled by Pagel’s <img src="https://latex.codecogs.com/png.latex?%5Clambda">, which multiplies the off-diagonal (shared ancestry) elements of the correlation matrix by <img src="https://latex.codecogs.com/png.latex?%5Clambda"> while leaving the diagonal untouched. <img src="https://latex.codecogs.com/png.latex?%5Clambda%20=%201"> recovers the full Brownian expectation; <img src="https://latex.codecogs.com/png.latex?%5Clambda%20=%200"> collapses the model back to OLS, since it implies no phylogenetic signal in the residuals at all. <img src="https://latex.codecogs.com/png.latex?%5Clambda"> is estimated by maximum likelihood alongside the regression coefficients, so the data themselves tell you how much phylogenetic correction is warranted (Pagel 1999; Freckleton et al.&nbsp;2002).</p>
</section>
<section id="worked-example-in-r" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="worked-example-in-r"><span class="header-section-number">4</span> Worked example in R</h2>
<p>The example below is fully self-contained: it simulates a tree and trait data with a known phylogenetic structure, so PGLS can be shown recovering the correct relationship where OLS does not.</p>
<section id="packages" class="level3" data-number="4.1">
<h3 data-number="4.1" class="anchored" data-anchor-id="packages"><span class="header-section-number">4.1</span> Packages</h3>
<p><code>ape</code> provides the phylogenetic infrastructure — tree objects, trait simulation, and the correlation structures (<code>corBrownian</code>, <code>corPagel</code>, <code>corMartins</code>, <code>corGrafen</code>) that plug directly into <code>nlme::gls()</code>. This combination is the base implementation of PGLS in R (Paradis and Schliep 2019; Pinheiro and Bates 2000). The <code>caper</code> package (Orme et al.&nbsp;2013) offers a popular alternative interface (<code>caper::pgls</code>) built specifically for comparative datasets, and <code>phytools</code> (Revell 2012) provides complementary tools for tree manipulation and visualization; either integrates well with the workflow below.</p>
<div id="644b9171" class="cell" data-execution_count="1">
<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;">install.packages</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;">"ape"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nlme"</span>))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># if not already installed</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ape)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tree handling and correlation structures</span></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(nlme)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># gls(), the workhorse for PGLS</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
The downloaded binary packages are in
    /var/folders/vm/xtvv8jb542s04t61c12lsnvr0000gn/T//RtmpgOJBH7/downloaded_packages</code></pre>
</div>
</div>
</section>
<section id="simulating-a-tree-and-correlated-trait-data" class="level3" data-number="4.2">
<h3 data-number="4.2" class="anchored" data-anchor-id="simulating-a-tree-and-correlated-trait-data"><span class="header-section-number">4.2</span> Simulating a tree and correlated trait data</h3>
<div id="a690a793" class="cell" data-execution_count="2">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">123</span>)</span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. A random ultrametric tree with 40 tips ("species")</span></span>
<span id="cb3-4">tree <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rcoal</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>)</span>
<span id="cb3-5">tree<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tip.label <span class="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;">"sp"</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;">40</span>)</span>
<span id="cb3-6"></span>
<span id="cb3-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. A predictor trait evolving under Brownian motion along the tree</span></span>
<span id="cb3-8">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;">rTraitCont</span>(tree, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BM"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sigma =</span> <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;"># 3. A response trait built as a linear function of x (true slope = 0.8),</span></span>
<span id="cb3-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    plus its own phylogenetically structured error term</span></span>
<span id="cb3-12">phylo_error <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rTraitCont</span>(tree, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BM"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sigma =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb3-13">y <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.8</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> phylo_error</span>
<span id="cb3-14"></span>
<span id="cb3-15">dat <span class="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;">species =</span> tree<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tip.label, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> y)</span>
<span id="cb3-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(dat) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>species</span>
<span id="cb3-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(dat)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 3</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">species</th>
<th data-quarto-table-cell-role="th" scope="col">x</th>
<th data-quarto-table-cell-role="th" scope="col">y</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">sp1</th>
<td>sp1</td>
<td>1.533555</td>
<td>1.119959</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">sp2</th>
<td>sp2</td>
<td>1.578064</td>
<td>1.176384</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">sp3</th>
<td>sp3</td>
<td>1.524573</td>
<td>1.050779</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">sp4</th>
<td>sp4</td>
<td>1.752620</td>
<td>1.301077</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">sp5</th>
<td>sp5</td>
<td>1.429647</td>
<td>2.070559</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">sp6</th>
<td>sp6</td>
<td>1.223539</td>
<td>1.970735</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="85ff2a99" class="cell" data-execution_count="3">
<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;">plot</span>(tree, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.tip.label =</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;">main =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Simulated 40-tip phylogeny"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/pgls/pgls_tutorial_files/figure-html/cell-4-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Because both <code>x</code> and the error term were generated under Brownian motion on the same tree, the residuals of any regression of <code>y</code> on <code>x</code> will themselves carry phylogenetic signal — exactly the situation PGLS is designed for.</p>
</section>
<section id="naive-ols-ignoring-the-phylogeny" class="level3" data-number="4.3">
<h3 data-number="4.3" class="anchored" data-anchor-id="naive-ols-ignoring-the-phylogeny"><span class="header-section-number">4.3</span> Naive OLS (ignoring the phylogeny)</h3>
<div id="1df030e0" class="cell" data-execution_count="4">
<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">m_ols <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</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> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> dat)</span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(m_ols)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>coefficients</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 2 × 4 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">Estimate</th>
<th data-quarto-table-cell-role="th" scope="col">Std. Error</th>
<th data-quarto-table-cell-role="th" scope="col">t value</th>
<th data-quarto-table-cell-role="th" scope="col">Pr(&gt;|t|)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">(Intercept)</th>
<td>-0.1581428</td>
<td>0.09203221</td>
<td>-1.718342</td>
<td>9.387331e-02</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">x</th>
<td>1.1539112</td>
<td>0.08223846</td>
<td>14.031284</td>
<td>1.304257e-16</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>OLS estimates the slope well above the true value of 0.8, with a tight standard error and an extremely small p-value. This is precisely the failure mode Felsenstein warned about: shared ancestry inflates the apparent strength and certainty of the relationship.</p>
</section>
<section id="pgls-assuming-brownian-motion" class="level3" data-number="4.4">
<h3 data-number="4.4" class="anchored" data-anchor-id="pgls-assuming-brownian-motion"><span class="header-section-number">4.4</span> PGLS assuming Brownian motion</h3>
<div id="c58e4e14" class="cell" data-execution_count="5">
<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">corBM <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">corBrownian</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;">phy =</span> tree, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">form =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>species)</span>
<span id="cb6-2">m_bm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gls</span>(y <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;">data =</span> dat, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">correlation =</span> corBM, <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;">"ML"</span>)</span>
<span id="cb6-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(m_bm)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tTable</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 2 × 4 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">Value</th>
<th data-quarto-table-cell-role="th" scope="col">Std.Error</th>
<th data-quarto-table-cell-role="th" scope="col">t-value</th>
<th data-quarto-table-cell-role="th" scope="col">p-value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">(Intercept)</th>
<td>-0.3596555</td>
<td>0.4085034</td>
<td>-0.8804222</td>
<td>3.841651e-01</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">x</th>
<td>0.8462925</td>
<td>0.0751379</td>
<td>11.2631903</td>
<td>1.131397e-13</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Once the Brownian covariance structure is built into the residuals, the slope estimate sits much closer to the true value (0.8), and the standard error is appropriately larger, reflecting the smaller effective sample size once phylogenetic redundancy is accounted for.</p>
</section>
<section id="pgls-with-pagels-λ-estimated-from-the-data" class="level3" data-number="4.5">
<h3 data-number="4.5" class="anchored" data-anchor-id="pgls-with-pagels-λ-estimated-from-the-data"><span class="header-section-number">4.5</span> PGLS with Pagel’s λ estimated from the data</h3>
<div id="b34bd377" class="cell" data-execution_count="6">
<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">corPagel_str <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">corPagel</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</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;">phy =</span> tree, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">form =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>species)</span>
<span id="cb7-2">m_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;">gls</span>(y <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;">data =</span> dat, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">correlation =</span> corPagel_str, <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;">"ML"</span>)</span>
<span id="cb7-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(m_lambda)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tTable</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 2 × 4 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">Value</th>
<th data-quarto-table-cell-role="th" scope="col">Std.Error</th>
<th data-quarto-table-cell-role="th" scope="col">t-value</th>
<th data-quarto-table-cell-role="th" scope="col">p-value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">(Intercept)</th>
<td>-0.3579659</td>
<td>0.41925874</td>
<td>-0.8538067</td>
<td>3.985625e-01</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">x</th>
<td>0.8421314</td>
<td>0.07516831</td>
<td>11.2032762</td>
<td>1.323633e-13</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="8d127da5" class="cell" data-execution_count="7">
<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">m_lambda<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>modelStruct<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>corStruct</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>Correlation structure of class corPagel representing
  lambda 
1.000392 </code></pre>
</div>
</div>
<p>Here λ is estimated at essentially 1, correctly recovering the fact that the simulated residual error really was generated under pure Brownian motion. In real data, λ will rarely be exactly 0 or 1; it is precisely this intermediate value that tells you how much phylogenetic correction the data support, rather than forcing an all-or-nothing assumption.</p>
</section>
<section id="comparing-models" class="level3" data-number="4.6">
<h3 data-number="4.6" class="anchored" data-anchor-id="comparing-models"><span class="header-section-number">4.6</span> Comparing models</h3>
<div id="24b59c2e" class="cell" data-execution_count="8">
<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;">AIC</span>(m_ols, m_bm, m_lambda)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 3 × 2</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">df</th>
<th data-quarto-table-cell-role="th" scope="col">AIC</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">m_ols</th>
<td>3</td>
<td>49.61137</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">m_bm</th>
<td>3</td>
<td>-35.29059</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">m_lambda</th>
<td>4</td>
<td>-33.89102</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Both PGLS models vastly outperform OLS by AIC, confirming that the phylogenetic structure in the residuals is real and that ignoring it costs a great deal of model fit. The Brownian and λ models are nearly indistinguishable here (as expected, since λ ≈ 1), but in general, letting λ be estimated rather than fixed at 1 is the safer default, since it nests both extremes.</p>
</section>
</section>
<section id="applying-this-to-your-own-data" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="applying-this-to-your-own-data"><span class="header-section-number">5</span> Applying this to your own data</h2>
<ol type="1">
<li><strong>Match your tips to your data.</strong> The tree’s tip labels and your data frame’s row names (or a species-name column) must correspond exactly; mismatches are the most common source of silent errors.</li>
<li><strong>Prune the tree to your species.</strong> Use <code>ape::keep.tip()</code> (or <code>drop.tip()</code>) to reduce a large reference phylogeny down to just the species in your dataset before fitting.</li>
<li><strong>Check for polytomies and zero-length branches.</strong> These can make some correlation structures numerically unstable; <code>ape::multi2di()</code> resolves polytomies at random for testing purposes, though ideally branch lengths should come from a proper phylogenetic analysis.</li>
<li><strong>Don’t assume Brownian motion by default.</strong> Fit λ (or, alternatively, Pagel’s κ or δ, or an Ornstein-Uhlenbeck model via <code>ape::corMartins</code>) and let the likelihood tell you which structure the data support, rather than hard-coding an assumption.</li>
<li><strong>Diagnose the fitted model</strong> as you would any GLS: examine standardized residuals for outliers or remaining structure, and consider whether the trait itself might need a transformation before modeling.</li>
</ol>
</section>
<section id="common-pitfalls" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="common-pitfalls"><span class="header-section-number">6</span> Common pitfalls</h2>
<ul>
<li>Fitting PGLS with <code>method = "REML"</code> when comparing models with different fixed effects via likelihood ratio tests or AIC; use <code>method = "ML"</code> for that purpose, and switch to REML only when your final model’s fixed effects are settled.</li>
<li>Treating a λ estimate of 0 as evidence that phylogeny “doesn’t matter” without checking the confidence interval on λ; with modest sample sizes, that interval is often wide.</li>
<li>Applying PGLS to trait pairs measured on different subsets of species without pruning both the tree and the data consistently.</li>
<li>Forgetting that PGLS corrects for correlated residuals due to shared ancestry — it does not, by itself, tell you whether a relationship is causal or convergent.</li>
</ul>
</section>
<section id="references" class="level2" data-number="7">
<h2 data-number="7" class="anchored" data-anchor-id="references"><span class="header-section-number">7</span> References</h2>
<p>Felsenstein, J. (1985). Phylogenies and the comparative method. <em>The American Naturalist</em>, 125(1), 1–15.</p>
<p>Freckleton, R. P., Harvey, P. H., &amp; Pagel, M. (2002). Phylogenetic analysis and comparative data: A test and review of evidence. <em>The American Naturalist</em>, 160(6), 712–726.</p>
<p>Grafen, A. (1989). The phylogenetic regression. <em>Philosophical Transactions of the Royal Society of London B</em>, 326(1233), 119–157.</p>
<p>Martins, E. P., &amp; Hansen, T. F. (1997). Phylogenies and the comparative method: A general approach to incorporating phylogenetic information into the analysis of interspecific data. <em>The American Naturalist</em>, 149(4), 646–667.</p>
<p>Orme, D., Freckleton, R., Thomas, G., Petzoldt, T., Fritz, S., Isaac, N., &amp; Pearse, W. (2013). <em>caper: Comparative Analyses of Phylogenetics and Evolution in R.</em> R package.</p>
<p>Pagel, M. (1999). Inferring the historical patterns of biological evolution. <em>Nature</em>, 401(6756), 877–884.</p>
<p>Paradis, E., &amp; Schliep, K. (2019). ape 5.0: An environment for modern phylogenetics and evolutionary analyses in R. <em>Bioinformatics</em>, 35(3), 526–528.</p>
<p>Pinheiro, J., &amp; Bates, D. (2000). <em>Mixed-Effects Models in S and S-PLUS.</em> Springer.</p>
<p>Revell, L. J. (2012). phytools: An R package for phylogenetic comparative biology (and other things). <em>Methods in Ecology and Evolution</em>, 3(2), 217–223.</p>
<p>Symonds, M. R. E., &amp; Blomberg, S. P. (2014). A primer on phylogenetic generalised least squares. In L. Z. Garamszegi (Ed.), <em>Modern Phylogenetic Comparative Methods and Their Application in Evolutionary Biology</em> (pp.&nbsp;105–130). Springer.</p>


</section>

 ]]></description>
  <category>Genetics</category>
  <category>Statistics</category>
  <category>Phylogenetics</category>
  <category>Tutorial</category>
  <guid>https://bntechie.github.io/tutorials/pgls/pgls_tutorial.html</guid>
  <pubDate>Tue, 21 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>From Raw Reads to GWAS-Ready Data</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/NGS_pipeline_raw_data_to_GWAS/ngs-to-gwas-pipeline.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/NGS_pipeline_raw_data_to_GWAS/images/ngs-to-gwas-pipeline.svg" alt="Five-stage pipeline diagram: FASTQ to BAM/CRAM to VCF to Phased and Imputed data to a GWAS-ready matrix, spanning Parts 1 through 3 of the tutorial" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The full path this tutorial walks, end to end: every stage below is a real, copy-pasteable command, from a sequencer’s raw output to a matrix ready for association testing.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">GATK</span> <span class="tag">PLINK</span> <span class="tag">Regenie</span> <span class="tag">HPC</span></p>
</div>
<section id="how-to-use-this" class="level2">
<h2 class="anchored" data-anchor-id="how-to-use-this">How to use this</h2>
<p>Each numbered step has a <strong>“What’s happening”</strong> explanation before the commands — read that first, then run the commands, then move on. No need to rush any of it. The tutorial is written for: - <strong>Part -1</strong>: environment setup on an Apple Silicon Mac (Lima Linux VM), since Linux-native bioinformatics tools don’t run natively on macOS ARM64 - <strong>Part 0</strong>: reference data staging, done once - <strong>Parts 1-3</strong>: the pipeline itself, runnable on your Mac at chr20/small-cohort scale now, and identically on real HPC later (just swap out the setup — every downstream command is the same either way)</p>
<p>Assume once you’re set up: - Reference: GRCh38 (<code>Homo_sapiens_assembly38.fasta</code>), matching known-sites VCFs from GATK resource bundle - Conda/mamba environments per tool group, to avoid dependency conflicts (set up in Part -1) - Everything here is designed to scale from “one trio on a laptop” to “thousands of WGS samples on a cluster” — the commands don’t change, only whether you prefix them with <code>sbatch</code></p>
<hr>
</section>
<section id="part--1-setting-up-your-environment-apple-silicon-mac-step-by-step" class="level2">
<h2 class="anchored" data-anchor-id="part--1-setting-up-your-environment-apple-silicon-mac-step-by-step">Part -1 — Setting up your environment (Apple Silicon Mac, step by step)</h2>
<p><strong>What’s happening here, conceptually first:</strong> almost every tool in this pipeline (GATK, bwa-mem2, samtools, plink) was built and tested for Linux. macOS is Unix-like but not Linux — different system libraries, different binary format. On Intel Macs this mostly didn’t matter because the CPU instruction set matched Linux x86_64 builds. On Apple Silicon (M-series), the CPU architecture itself (ARM64) is different, so pre-built Linux binaries won’t run at all, and macOS-native ARM64 builds of these tools are incomplete or missing on bioconda. The fix is to run a real Linux virtual machine on your Mac — not emulation of individual programs, but an actual Linux kernel and userspace — so every tool installs and runs exactly as it would on your future HPC. This also means everything you learn about the environment transfers directly.</p>
<section id="step-1-install-lima-the-vm-manager" class="level3">
<h3 class="anchored" data-anchor-id="step-1-install-lima-the-vm-manager">Step 1: Install Lima (the VM manager)</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Homebrew is macOS's package manager — if you don't have it:</span></span>
<span id="cb1-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/bin/bash</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-fsSL</span> https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Lima runs a lightweight Linux VM with automatic file-sharing back to macOS</span></span>
<span id="cb1-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install lima</span></code></pre></div></div>
<p><em>What this does:</em> Lima creates a small Linux VM (using Apple’s native <code>vz</code> virtualization framework on M-series, so it’s fast — not slow software emulation) and automatically mounts your home directory inside it, so files you create feel local either way.</p>
</section>
<section id="step-2-start-a-linux-vm-sized-for-this-work" class="level3">
<h3 class="anchored" data-anchor-id="step-2-start-a-linux-vm-sized-for-this-work">Step 2: Start a Linux VM sized for this work</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">limactl</span> start <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cpus</span> 12 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--memory</span> 32 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--disk</span> 150 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--arch</span> aarch64 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--vm-type</span> vz default</span></code></pre></div></div>
<p><em>What each flag does:</em> - <code>--cpus 12</code> — give the VM 12 of your performance cores; leaves headroom for macOS itself - <code>--memory 32</code> — 32GB to the VM out of your 48GB total; leaves the rest for macOS + any GUI tools you’re running alongside - <code>--disk 150</code> — reference genomes, VCFs, and intermediate BAMs eat disk fast; 150GB is a safe starting allocation for chr20-scale work (you’ll want more for full-genome runs) - <code>--arch aarch64</code> — native ARM64 Linux, matching your M5 Pro’s actual architecture (no translation layer) - <code>--vm-type vz</code> — Apple’s native virtualization (faster than the older QEMU-based default on Apple Silicon)</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Drop into a shell inside the VM — this is now a real Linux machine</span></span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">limactl</span> shell default</span></code></pre></div></div>
<p>Everything from here on runs <em>inside</em> this Lima shell, not in your normal macOS terminal. Your prompt will change to reflect this. To leave, just <code>exit</code>; to come back later, <code>limactl start default</code> (if stopped) then <code>limactl shell default</code> again.</p>
</section>
<section id="step-3-install-miniforgemamba-inside-the-vm" class="level3">
<h3 class="anchored" data-anchor-id="step-3-install-miniforgemamba-inside-the-vm">Step 3: Install Miniforge/mamba inside the VM</h3>
<p><strong>What’s happening:</strong> conda/mamba is a package + environment manager built specifically for scientific software — it resolves complex dependency chains (a specific version of GATK needing a specific Java version needing specific system libraries) that would be painful to install by hand. <code>mamba</code> is a faster drop-in replacement for <code>conda</code>’s solver. We install it fresh inside the Linux VM (not on macOS) since that’s where all the Linux binaries will actually run.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-L</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh"</span></span>
<span id="cb4-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bash</span> Miniforge3-Linux-aarch64.sh <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-b</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$HOME</span>/miniforge3</span>
<span id="cb4-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">source</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$HOME</span>/miniforge3/bin/activate</span>
<span id="cb4-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">conda</span> init bash</span>
<span id="cb4-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># close and reopen the Lima shell (or `source ~/.bashrc`) for this to take effect</span></span></code></pre></div></div>
</section>
<section id="step-4-create-isolated-environments-per-tool-group" class="level3">
<h3 class="anchored" data-anchor-id="step-4-create-isolated-environments-per-tool-group">Step 4: Create isolated environments per tool group</h3>
<p><strong>What’s happening:</strong> different bioinformatics tools sometimes need conflicting versions of shared libraries (e.g.&nbsp;different Python or htslib versions). Rather than fighting version conflicts in one giant environment, we create separate named environments — one activated at a time — so each tool group gets exactly the dependencies it wants without breaking another.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">mamba</span> create <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> ngs-core <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> bioconda <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> conda-forge <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-2">  fastp fastqc multiqc bwa-mem2 samtools sambamba gatk4 bcftools <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-3">  vcftools plink plink2 mosdepth <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-y</span></span>
<span id="cb5-4"></span>
<span id="cb5-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">mamba</span> create <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> ngs-sv <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> bioconda manta smoove truvari <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-y</span></span>
<span id="cb5-6"></span>
<span id="cb5-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">mamba</span> create <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> ngs-phase <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> bioconda shapeit4 beagle eagle <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-y</span></span>
<span id="cb5-8"></span>
<span id="cb5-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">mamba</span> create <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> ngs-gwas <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> bioconda <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> conda-forge regenie <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-y</span></span></code></pre></div></div>
<p><em>Why split this way:</em> <code>ngs-core</code> covers Part 1 + most of Part 2 (alignment, calling, basic QC). <code>ngs-sv</code> isolates the structural-variant callers, which sometimes pin older/different library versions. <code>ngs-phase</code> and <code>ngs-gwas</code> isolate the Part 3 tools similarly. You’ll <code>conda activate ngs-core</code> (etc.) before running the relevant commands — one environment active at a time.</p>
<p><strong>Before trusting any of this, verify the key tools actually resolved to working binaries</strong> (aarch64 bioconda coverage isn’t 100% for every package):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">conda</span> activate ngs-core</span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bwa-mem2</span> version</span>
<span id="cb6-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--version</span></span>
<span id="cb6-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--version</span></span></code></pre></div></div>
<p>If any of these fail to install or run, the fallback is forcing that specific package through the <code>linux-64</code> (Intel Linux) channel, which the VM’s Linux kernel can still execute via <code>qemu-user-static</code> emulation — slower for that one tool, but everything else stays native:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">mamba</span> create <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> ngs-core-x64 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--platform</span> linux-64 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> bioconda <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> conda-forge <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>tool-that-failed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> -y</span></code></pre></div></div>
</section>
<section id="step-5-confirm-your-resource-allocation-matches-what-you-planned" class="level3">
<h3 class="anchored" data-anchor-id="step-5-confirm-your-resource-allocation-matches-what-you-planned">Step 5: Confirm your resource allocation matches what you planned</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nproc</span>                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># should show 12 (or whatever you allocated)</span></span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">free</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-h</span>              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># should show ~32GB total</span></span>
<span id="cb8-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">df</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-h</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$HOME</span>          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># confirm your disk allocation</span></span></code></pre></div></div>
</section>
<section id="step-6-a-sane-working-directory-layout" class="level3">
<h3 class="anchored" data-anchor-id="step-6-a-sane-working-directory-layout">Step 6: A sane working directory layout</h3>
<p><strong>What’s happening:</strong> genomics pipelines generate a <em>lot</em> of intermediate files (raw reads → trimmed reads → BAM → dedup BAM → recalibrated BAM → GVCF → joint VCF → filtered VCF → phased VCF → imputed VCF, per sample, per chromosome). Without a deliberate layout you will lose track of what’s what within a day. This structure mirrors what you’ll see on real HPC filesystems.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> ~/ngs_work/<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{refs</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">raw</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">work/{trimmed</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">aligned</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">dedup</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">bqsr</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">gvcf</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">joint</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">filtered</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">phased</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">imputed}</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">qc</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">scripts}</span></span>
<span id="cb9-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> ~/ngs_work</span></code></pre></div></div>
<p>From here, Part 0 (reference staging) and Part 1 onward all run inside this Lima Linux shell, with <code>ngs-core</code> (or the relevant environment) activated.</p>
<hr>
</section>
</section>
<section id="part-0-staging-reference-data-run-once-reuse-across-all-samples" class="level2">
<h2 class="anchored" data-anchor-id="part-0-staging-reference-data-run-once-reuse-across-all-samples">Part 0 — Staging reference data (run once, reuse across all samples)</h2>
<p><strong>What’s happening:</strong> every downstream step needs a common coordinate system to align reads to and a set of “known truth” variant sites to calibrate against. This section downloads exactly those shared resources once, so every sample you process afterward references the identical files — consistency here is what makes results comparable across samples and, eventually, across collaborating cohorts like FinnGen partners.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> refs/<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{genome</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">vqsr</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">phasing</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">giab}</span></span>
<span id="cb10-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> refs</span>
<span id="cb10-3"></span>
<span id="cb10-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- GRCh38 reference + GATK resource bundle (public, no GCP account required) ---</span></span>
<span id="cb10-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gsutil</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> cp gs://gcp-public-data--broad-references/hg38/v0/Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-6">  gs://gcp-public-data--broad-references/hg38/v0/Homo_sapiens_assembly38.fasta.fai <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-7">  gs://gcp-public-data--broad-references/hg38/v0/Homo_sapiens_assembly38.dict <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-8">  genome/</span>
<span id="cb10-9"></span>
<span id="cb10-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gsutil</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> cp <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-11">  gs://gcp-public-data--broad-references/hg38/v0/Homo_sapiens_assembly38.dbsnp138.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-12">  gs://gcp-public-data--broad-references/hg38/v0/Homo_sapiens_assembly38.dbsnp138.vcf.gz.tbi <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-13">  gs://gcp-public-data--broad-references/hg38/v0/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-14">  gs://gcp-public-data--broad-references/hg38/v0/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz.tbi <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-15">  gs://gcp-public-data--broad-references/hg38/v0/Homo_sapiens_assembly38.known_indels.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-16">  gs://gcp-public-data--broad-references/hg38/v0/Homo_sapiens_assembly38.known_indels.vcf.gz.tbi <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-17">  vqsr/</span>
<span id="cb10-18"></span>
<span id="cb10-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- VQSR training/truth resources ---</span></span>
<span id="cb10-20"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gsutil</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> cp <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-21">  gs://gcp-public-data--broad-references/hg38/v0/hapmap_3.3.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-22">  gs://gcp-public-data--broad-references/hg38/v0/1000G_omni2.5.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-23">  gs://gcp-public-data--broad-references/hg38/v0/1000G_phase1.snps.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-24">  vqsr/</span>
<span id="cb10-25"></span>
<span id="cb10-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- Index BWA-MEM2 reference (do this once, it's slow) ---</span></span>
<span id="cb10-27"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bwa-mem2</span> index genome/Homo_sapiens_assembly38.fasta</span>
<span id="cb10-28"></span>
<span id="cb10-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- 1000 Genomes high-coverage phased panel (for SHAPEIT4/Eagle/Beagle) ---</span></span>
<span id="cb10-30"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chr <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span> 1 22<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">do</span></span>
<span id="cb10-31">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wget</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-P</span> phasing/ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-32">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"http://ftp.1000genomes.ebi.ac.uk/vol1/ftp/data_collections/1000G_2504_high_coverage/working/20220422_3202_phased_SNV_INDEL_SV/1kGP_high_coverage_Illumina.chr</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">${chr}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">.filtered.SNV_INDEL_SV_phased_panel.vcf.gz"</span></span>
<span id="cb10-33"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">done</span></span>
<span id="cb10-34"></span>
<span id="cb10-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- Genetic maps (Beagle/Eagle format, GRCh38) ---</span></span>
<span id="cb10-36"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wget</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-P</span> phasing/ https://bochet.gcc.biostat.washington.edu/beagle/genetic_maps/plink.GRCh38.map.zip</span>
<span id="cb10-37"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unzip</span> phasing/plink.GRCh38.map.zip <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-d</span> phasing/</span>
<span id="cb10-38"></span>
<span id="cb10-39"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- GIAB truth set (HG002) for validating your pipeline against known-truth calls ---</span></span>
<span id="cb10-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Browse the current directory tree first — URL paths shift periodically:</span></span>
<span id="cb10-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/</span></span>
<span id="cb10-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Grab the GRCh38-aligned AJ-trio (HG002/3/4) FASTQ or CRAM set from there.</span></span>
<span id="cb10-43"></span>
<span id="cb10-44"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- Sanity checksum everything before trusting it ---</span></span>
<span id="cb10-45"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">find</span> . <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-type</span> f <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\(</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;">"*.vcf.gz"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</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;">"*.fasta"</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\)</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-exec</span> md5sum {} <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> checksums.txt</span></code></pre></div></div>
<p><strong>If <code>gsutil</code> isn’t available on your HPC</strong> (common — many clusters block outbound GCS auth), use the plain HTTPS mirror instead: prefix each path with <code>https://storage.googleapis.com/gcp-public-data--broad-references/...</code> and swap <code>gsutil -m cp</code> for <code>wget</code>.</p>
<p><strong>What each of these files is actually for</strong>, since it matters later when something goes wrong: - <code>Homo_sapiens_assembly38.fasta</code> (+<code>.fai</code>/<code>.dict</code>) — the coordinate system itself. Every position you’ll ever report (“chr20:1234567”) is only meaningful relative to this exact file. Mixing reference builds (GRCh37 vs GRCh38) between steps is one of the most common and hardest-to-notice pipeline bugs. - <code>dbsnp138.vcf.gz</code> — a catalog of previously observed variant positions, used to annotate/flag known vs novel sites and as a training resource - <code>Mills...indels</code> and <code>known_indels</code> — curated “trustworthy” indel sites, used specifically by BQSR to know which mismatches are real biology (leave alone) vs sequencing error (recalibrate away) - <code>hapmap</code>, <code>1000G_omni2.5</code>, <code>1000G_phase1.snps</code> — high-confidence SNP truth sets used later by VQSR to <em>learn</em> what a real variant’s statistical signature looks like, versus an artifact’s - the 1000G phased panel + genetic maps — used in Part 3 for phasing and imputation, which need a large reference cohort’s known haplotype structure to infer missing/uncertain genotypes in your own samples - GIAB HG002 — the one sample in this whole tutorial where you actually <em>know</em> the right answer, which is why it’s used for validation exercises later</p>
<hr>
</section>
<section id="part-1-raw-fastq-analysis-ready-bamcram" class="level1">
<h1>PART 1 — Raw FASTQ → Analysis-Ready BAM/CRAM</h1>
<section id="sanity-check-and-qc-raw-reads" class="level2">
<h2 class="anchored" data-anchor-id="sanity-check-and-qc-raw-reads">1.1 Sanity-check and QC raw reads</h2>
<p><strong>What’s happening:</strong> a sequencer doesn’t output “the genome” — it outputs millions of short, overlapping, imperfect text reads (FASTQ format: a DNA sequence + a per-base quality score for each read). Before you spend hours aligning bad data, you check whether the raw reads themselves are trustworthy: are quality scores dropping off, is there leftover adapter sequence the sequencer failed to strip, is the GC content distribution what you’d expect from human DNA (a skew can mean contamination). <code>fastp</code> then actively cleans the reads — trimming adapters and low-quality bases — before anything touches the reference genome.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Per-sample QC</span></span>
<span id="cb11-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">fastqc</span> sample_R1.fastq.gz sample_R2.fastq.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> qc/ <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> 8</span>
<span id="cb11-3"></span>
<span id="cb11-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Adapter trimming + quality filtering + auto-detection of adapters (fastp is faster than trimmomatic and gives a JSON report)</span></span>
<span id="cb11-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">fastp</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> sample_R1.fastq.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> sample_R2.fastq.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> trimmed_R1.fastq.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> trimmed_R2.fastq.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--detect_adapter_for_pe</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--qualified_quality_phred</span> 20 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--length_required</span> 36 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--thread</span> 8 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--json</span> fastp_sample.json <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--html</span> fastp_sample.html</span>
<span id="cb11-13"></span>
<span id="cb11-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Aggregate QC across a whole batch — this is what you'll actually eyeball daily</span></span>
<span id="cb11-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">multiqc</span> qc/ fastp_<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span>.json <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> multiqc_report/</span></code></pre></div></div>
<p><strong>What to flag before proceeding:</strong> per-base quality drop-off, adapter content &gt;5%, GC content bimodality (contamination), duplication rate pre-alignment (library complexity proxy).</p>
</section>
<section id="alignment-bwa-mem2-faster-drop-in-replacement-for-bwa-mem-same-output" class="level2">
<h2 class="anchored" data-anchor-id="alignment-bwa-mem2-faster-drop-in-replacement-for-bwa-mem-same-output">1.2 Alignment (BWA-MEM2 — faster drop-in replacement for BWA-MEM, same output)</h2>
<p><strong>What’s happening:</strong> alignment is the step where each of those millions of short reads gets placed at its most likely position of origin on the reference genome. <code>bwa-mem2</code> does this using an FM-index (a compressed, searchable representation of the whole genome built by <code>bwa-mem2 index</code>) to rapidly find candidate matching regions, then does a proper local alignment (allowing for mismatches/small indels from real biological variation or sequencing error) to pick the best position and produce a CIGAR string describing exactly how the read lines up. The output SAM/BAM format is essentially “for every read: where it landed, how well it matched, and how confident we are.” The read group (<code>-R</code> string) isn’t decoration — it’s metadata GATK relies on downstream to know which reads came from the same physical sequencing run, which matters for error-model calibration in BQSR and for correctly attributing genotypes to the right sample.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb12-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Index reference once</span></span>
<span id="cb12-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bwa-mem2</span> index Homo_sapiens_assembly38.fasta</span>
<span id="cb12-3"></span>
<span id="cb12-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Align with proper read group (mandatory for GATK downstream — get this wrong and BQSR/HaplotypeCaller will silently misbehave)</span></span>
<span id="cb12-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bwa-mem2</span> mem <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> 16 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb12-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"@RG\tID:sample1_L001\tSM:sample1\tPL:ILLUMINA\tLB:lib1\tPU:flowcell1.lane1"</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb12-7">  Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb12-8">  trimmed_R1.fastq.gz trimmed_R2.fastq.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb12-9">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> sort <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-@</span> 8 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> sample1.sorted.bam <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-</span></span>
<span id="cb12-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> index sample1.sorted.bam</span></code></pre></div></div>
<p>For multi-lane samples, align each lane separately with distinct <code>ID</code>/<code>PU</code>, same <code>SM</code>, then merge:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb13-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> merge <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-@</span> 8 sample1.merged.bam sample1_L001.sorted.bam sample1_L002.sorted.bam</span>
<span id="cb13-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> index sample1.merged.bam</span></code></pre></div></div>
</section>
<section id="mark-duplicates" class="level2">
<h2 class="anchored" data-anchor-id="mark-duplicates">1.3 Mark duplicates</h2>
<p><strong>What’s happening:</strong> PCR amplification during library prep, and sometimes the sequencer itself (optical duplicates), can produce multiple reads that are actually copies of the exact same original DNA fragment rather than independent observations. If you count these as independent evidence, you’ll inflate confidence in variant calls that are really just one PCR-duplicated read counted five times. This step doesn’t delete duplicates — it <em>flags</em> them (a SAM flag bit) so downstream tools like HaplotypeCaller know to down-weight or ignore them, while the raw data is preserved for auditing.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># GATK's MarkDuplicatesSpark parallelizes well; sambamba markdup is a lighter/faster alternative for large WGS batches</span></span>
<span id="cb14-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> MarkDuplicatesSpark <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb14-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> sample1.merged.bam <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb14-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> sample1.dedup.bam <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb14-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-M</span> sample1.dedup_metrics.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb14-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--spark-master</span> local<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">16</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb14-7"></span>
<span id="cb14-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Alternative (often faster at scale):</span></span>
<span id="cb14-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">sambamba</span> markdup <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> 16 sample1.merged.bam sample1.dedup.bam</span></code></pre></div></div>
</section>
<section id="base-quality-score-recalibration-bqsr" class="level2">
<h2 class="anchored" data-anchor-id="base-quality-score-recalibration-bqsr">1.4 Base Quality Score Recalibration (BQSR)</h2>
<p><strong>What’s happening:</strong> the sequencer’s own per-base quality scores are a machine’s <em>estimate</em> of its own error rate, and that estimate is systematically biased in predictable ways — by position in the read, by the specific sequence context, by which machine cycle produced the base. BQSR builds an empirical error model by comparing observed mismatches against the <em>known</em> truth sites (dbSNP/Mills/known indels you staged in Part 0) — any mismatch at a known-variant site is assumed to be real biology, while mismatches everywhere else are assumed to be sequencing error, and the model learns the actual error rate per context. <code>ApplyBQSR</code> then rewrites each base’s quality score using this corrected model. Downstream variant callers weight evidence by these quality scores directly, so this step measurably improves variant calling accuracy — it’s not cosmetic.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb15-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> BaseRecalibrator <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> sample1.dedup.bam <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--known-sites</span> Homo_sapiens_assembly38.dbsnp138.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--known-sites</span> Mills_and_1000G_gold_standard.indels.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--known-sites</span> Homo_sapiens_assembly38.known_indels.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> sample1.recal.table</span>
<span id="cb15-8"></span>
<span id="cb15-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> ApplyBQSR <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> sample1.dedup.bam <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bqsr-recal-file</span> sample1.recal.table <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> sample1.final.bam</span></code></pre></div></div>
</section>
<section id="convert-to-cram-mandatory-at-scale-40-60-smaller-than-bam-and-this-matters-a-lot-once-youre-storing-thousands-of-wgs-samples" class="level2">
<h2 class="anchored" data-anchor-id="convert-to-cram-mandatory-at-scale-40-60-smaller-than-bam-and-this-matters-a-lot-once-youre-storing-thousands-of-wgs-samples">1.5 Convert to CRAM (mandatory at scale — ~40-60% smaller than BAM, and this matters a lot once you’re storing thousands of WGS samples)</h2>
<p><strong>What’s happening:</strong> BAM stores every read’s full sequence even though most of it matches the reference exactly. CRAM instead stores only the <em>differences</em> from the reference (which you supply via <code>-T</code>) plus a reference-independent fallback for unmapped/unusual reads, then compresses that much smaller representation further. The tradeoff is that a CRAM file is meaningless without the exact reference FASTA that produced it — which is exactly why Part 0 pinned one canonical reference file for the whole pipeline.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb16-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> view <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-T</span> Homo_sapiens_assembly38.fasta <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-C</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-@</span> 8 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb16-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> sample1.final.cram sample1.final.bam</span>
<span id="cb16-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> index sample1.final.cram</span></code></pre></div></div>
</section>
<section id="post-alignment-qc-gates-run-these-before-anyone-trusts-the-sample" class="level2">
<h2 class="anchored" data-anchor-id="post-alignment-qc-gates-run-these-before-anyone-trusts-the-sample">1.6 Post-alignment QC gates — run these before anyone trusts the sample</h2>
<p><strong>What’s happening:</strong> this is the checkpoint where you decide, quantitatively, whether a sample is good enough to keep processing or needs to be flagged/excluded/re-sequenced. Each metric answers a distinct question: coverage/depth (<code>samtools coverage</code>, <code>mosdepth</code>) — did we sequence deeply enough at each position to call genotypes confidently, and are there suspicious dropouts that might indicate a deletion or a capture failure; <code>samtools stats</code>/<code>flagstat</code> — did alignment itself go well (mapping rate, proper pairing, insert size distribution matching the library prep expectation); contamination (<code>VerifyBamID2</code>) — is this BAM secretly a mixture of two individuals’ DNA (a real risk in any wet-lab pipeline, from sample swaps to cross-contamination), measured by checking whether allele frequencies at known-variant sites look like they came from one clean genome or a mixture.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb17-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Coverage / depth</span></span>
<span id="cb17-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> coverage sample1.final.cram <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> sample1.coverage.txt</span>
<span id="cb17-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">mosdepth</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--by</span> 500 sample1 sample1.final.cram   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># fast, windowed depth — great for spotting CNV-scale dropouts</span></span>
<span id="cb17-4"></span>
<span id="cb17-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Insert size, alignment stats</span></span>
<span id="cb17-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> stats sample1.final.cram <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> sample1.stats.txt</span>
<span id="cb17-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> flagstat sample1.final.cram <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> sample1.flagstat.txt</span>
<span id="cb17-8"></span>
<span id="cb17-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Contamination check (critical for WGS/WES QC gates — cross-sample or cross-species contamination)</span></span>
<span id="cb17-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> CollectFingerprintingDetailMetrics <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb17-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> sample1.final.cram <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb17-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> sample1.fingerprint <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--HAPLOTYPE_MAP</span> hapmap_3.3.hg38.map</span>
<span id="cb17-13"></span>
<span id="cb17-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">VerifyBamID2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--SVDPrefix</span> resource/1000g.phase3 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb17-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--Reference</span> Homo_sapiens_assembly38.fasta <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--BamFile</span> sample1.final.cram</span></code></pre></div></div>
<p><strong>Standard gate thresholds to codify into a QC pipeline:</strong> mean coverage (≥30x WGS / ≥50-100x on-target WES), %reads mapped ≥95%, duplication rate &lt;20%, contamination (FREEMIX) &lt;3%, sex-check concordance (via chrX/Y coverage ratio) against reported sex.</p>
<hr>
</section>
</section>
<section id="part-2-variant-calling-joint-genotyping-sv-calling-and-vcf-level-qc" class="level1">
<h1>PART 2 — Variant Calling, Joint Genotyping, SV Calling, and VCF-Level QC</h1>
<section id="per-sample-gvcf-calling-gatks-scalable-design-call-once-per-sample-joint-genotype-later-without-re-calling" class="level2">
<h2 class="anchored" data-anchor-id="per-sample-gvcf-calling-gatks-scalable-design-call-once-per-sample-joint-genotype-later-without-re-calling">2.1 Per-sample GVCF calling (GATK’s scalable design — call once per sample, joint-genotype later without re-calling)</h2>
<p><strong>What’s happening:</strong> HaplotypeCaller doesn’t just look at one position at a time — it locally reassembles the reads in each region into candidate haplotypes (via a local de Bruijn-like graph), then uses a statistical model to score how well each candidate haplotype explains the observed reads, which is what lets it call indels accurately and not just simple substitutions. Critically, we run it in GVCF mode (<code>-ERC GVCF</code>), which records a confidence estimate at <em>every</em> position — including ones with no variant — rather than only variant sites. This is the design that makes cohort-scale calling tractable: if you called each sample against a fixed set of “known” variant sites, you’d never discover a variant that’s rare or private to your cohort; GVCF mode defers the “is this actually a variant across the cohort” decision to the joint-genotyping step next, while still only running the expensive per-read reassembly once per sample.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb18-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> HaplotypeCaller <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb18-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> sample1.final.cram <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb18-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb18-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> sample1.g.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb18-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-ERC</span> GVCF <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb18-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--native-pair-hmm-threads</span> 8</span></code></pre></div></div>
<p>For WES, restrict to the capture region:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb19-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> HaplotypeCaller <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb19-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> sample1.final.cram <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb19-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-L</span> capture_targets.interval_list <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-ip</span> 100 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb19-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> sample1.g.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-ERC</span> GVCF</span></code></pre></div></div>
</section>
<section id="joint-genotyping-across-a-cohort-this-is-where-finngen-scale-joint-calling-happens" class="level2">
<h2 class="anchored" data-anchor-id="joint-genotyping-across-a-cohort-this-is-where-finngen-scale-joint-calling-happens">2.2 Joint genotyping across a cohort (this is where FinnGen-scale joint calling happens)</h2>
<p><strong>What’s happening:</strong> <code>GenomicsDBImport</code> merges each sample’s per-position confidence records (from the GVCFs) into an efficient, queryable on-disk database — think of it as a sparse matrix of “sample × genomic position → evidence,” built specifically so it scales to thousands of samples without exploding in size or IO cost, which flat <code>CombineGVCFs</code> doesn’t do well past a few hundred samples. <code>GenotypeGVCFs</code> then makes the actual joint calling decision: at every position where <em>any</em> sample showed evidence of a variant, it looks across <em>all</em> samples simultaneously to decide the final genotype for each individual — a site that looked marginal in one sample alone can become a confident call once you see the same allele recurring across the cohort, which is exactly the statistical leverage joint calling gives you over calling each sample in isolation.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Consolidate GVCFs — GenomicsDBImport scales far better than CombineGVCFs for thousands of samples</span></span>
<span id="cb20-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> GenomicsDBImport <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb20-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--genomicsdb-workspace-path</span> cohort_db_chr1 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb20-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-L</span> chr1 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb20-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--sample-name-map</span> cohort.sample_map.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb20-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--batch-size</span> 50 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb20-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--reader-threads</span> 8</span>
<span id="cb20-8"></span>
<span id="cb20-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sample_map.txt format: sample_id&lt;TAB&gt;path/to/sample.g.vcf.gz  (one per line)</span></span>
<span id="cb20-10"></span>
<span id="cb20-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> GenotypeGVCFs <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb20-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb20-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-V</span> gendb://cohort_db_chr1 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb20-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> cohort_chr1.vcf.gz</span></code></pre></div></div>
<p>Run per-chromosome in parallel across the cluster, then merge:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb21-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> concat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-Oz</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> cohort.joint.vcf.gz cohort_chr<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span>.vcf.gz</span>
<span id="cb21-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> index <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> cohort.joint.vcf.gz</span></code></pre></div></div>
</section>
<section id="variant-quality-score-recalibration-vqsr-the-actual-filtering-step-that-matters-most-for-downstream-gwas-validity" class="level2">
<h2 class="anchored" data-anchor-id="variant-quality-score-recalibration-vqsr-the-actual-filtering-step-that-matters-most-for-downstream-gwas-validity">2.3 Variant Quality Score Recalibration (VQSR) — the actual filtering step that matters most for downstream GWAS validity</h2>
<p><strong>What’s happening:</strong> raw joint-called variants include real biology <em>and</em> a substantial number of technical artifacts (mapping errors, systematic sequencing biases, assembly mistakes in repetitive regions). A single hard threshold on any one annotation (e.g.&nbsp;“reject anything with QD &lt; 2”) is crude because artifacts don’t look identical across the genome. VQSR instead trains a Gaussian mixture model on several per-variant annotations simultaneously (<code>QD</code> = quality normalized by depth, <code>MQ</code> = mapping quality, <code>FS</code>/<code>SOR</code> = strand bias measures, <code>ReadPosRankSum</code> = whether the variant allele clusters suspiciously at read ends) using the truth/training sites from Part 0 as positive examples of “this is what real variants look like.” Every variant in your callset then gets a score for how well it resembles the truth-set variants’ statistical fingerprint, and <code>ApplyVQSR</code> cuts at a sensitivity threshold (e.g.&nbsp;99.5% — “keep the score cutoff that retains 99.5% of the training truth sites”) rather than an arbitrary single-metric threshold. This is genuinely more powerful than hard filtering because it learns the <em>joint</em> distribution of what real variants look like across all metrics at once, not each metric independently.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb22-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># SNPs</span></span>
<span id="cb22-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> VariantRecalibrator <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-V</span> cohort.joint.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--resource:hapmap,known</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>false,training=true,truth=true,prior=15.0 hapmap_3.3.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--resource:omni,known</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>false,training=true,truth=false,prior=12.0 1000G_omni2.5.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--resource:1000G,known</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>false,training=true,truth=false,prior=10.0 1000G_phase1.snps.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--resource:dbsnp,known</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>true,training=false,truth=false,prior=2.0 Homo_sapiens_assembly38.dbsnp138.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> QD <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> MQ <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> MQRankSum <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> ReadPosRankSum <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> FS <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> SOR <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-mode</span> SNP <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> cohort.snps.recal <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--tranches-file</span> cohort.snps.tranches</span>
<span id="cb22-11"></span>
<span id="cb22-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> ApplyVQSR <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-V</span> cohort.joint.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--recal-file</span> cohort.snps.recal <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--tranches-file</span> cohort.snps.tranches <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--truth-sensitivity-filter-level</span> 99.5 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-mode</span> SNP <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> cohort.snps.filtered.vcf.gz</span>
<span id="cb22-17"></span>
<span id="cb22-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Indels (same pattern, different annotations/resources)</span></span>
<span id="cb22-19"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> VariantRecalibrator <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-20">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-V</span> cohort.snps.filtered.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-21">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--resource:mills,known</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>false,training=true,truth=true,prior=12.0 Mills_and_1000G_gold_standard.indels.hg38.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--resource:dbsnp,known</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>true,training=false,truth=false,prior=2.0 Homo_sapiens_assembly38.dbsnp138.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-23">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> QD <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> FS <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> ReadPosRankSum <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> MQRankSum <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-an</span> SOR <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-24">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-mode</span> INDEL <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> cohort.indels.recal <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--tranches-file</span> cohort.indels.tranches</span>
<span id="cb22-25"></span>
<span id="cb22-26"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> ApplyVQSR <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-27">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> Homo_sapiens_assembly38.fasta <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-V</span> cohort.snps.filtered.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-28">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--recal-file</span> cohort.indels.recal <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--tranches-file</span> cohort.indels.tranches <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-29">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--truth-sensitivity-filter-level</span> 99.0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-mode</span> INDEL <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-30">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> cohort.final.vcf.gz</span></code></pre></div></div>
<p><em>For cohorts too small for reliable VQSR (roughly &lt;30 samples), fall back to hard filtering with <code>VariantFiltration</code> using the same annotation thresholds as tranches approximate — worth knowing both paths since production cohorts often need to bootstrap from small pilot batches.</em></p>
</section>
<section id="structural-variants-snvsindels-are-not-the-whole-story-this-is-explicitly-in-scope-per-the-jd" class="level2">
<h2 class="anchored" data-anchor-id="structural-variants-snvsindels-are-not-the-whole-story-this-is-explicitly-in-scope-per-the-jd">2.4 Structural variants (SNVs/indels are not the whole story — this is explicitly in scope per the JD)</h2>
<p><strong>What’s happening:</strong> HaplotypeCaller is built for small variants (SNVs and indels typically under ~50bp) because its local reassembly approach breaks down for larger rearrangements. Structural variants — deletions, duplications, insertions, inversions, translocations spanning hundreds to millions of bases — need different evidence entirely: read pairs whose insert size or orientation doesn’t match expectation, split reads that align partially to two different genomic locations, and coverage depth changes. Manta scans for exactly these signal types and assembles breakpoints from them; smoove (built on <code>lumpy</code>+<code>svtyper</code>+<code>duphold</code>) is a lighter, faster alternative tuned for running consistently across large cohorts, followed by a merge/genotype step so that an SV detected in one sample gets properly genotyped (present/absent/heterozygous) across every other sample in the cohort, the SV equivalent of joint genotyping in section 2.2.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb23-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Manta — good general-purpose SV caller (deletions, duplications, insertions, inversions, translocations)</span></span>
<span id="cb23-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">configManta.py</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bam</span> sample1.final.cram <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--referenceFasta</span> Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb23-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--runDir</span> manta_sample1</span>
<span id="cb23-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">manta_sample1/runWorkflow.py</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> 8</span>
<span id="cb23-5"></span>
<span id="cb23-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># smoove — lighter-weight, good for cohort-scale SV joint calling</span></span>
<span id="cb23-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">smoove</span> call <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--outdir</span> sv_out/ <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--name</span> sample1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--fasta</span> Homo_sapiens_assembly38.fasta <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb23-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--exclude</span> exclude.cnvnator_100bp.GRCh38.20170403.bed <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> 1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--genotype</span> sample1.final.cram</span>
<span id="cb23-9"></span>
<span id="cb23-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">smoove</span> merge <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--name</span> cohort <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--fasta</span> Homo_sapiens_assembly38.fasta sv_out/<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span>.genotyped.vcf.gz</span>
<span id="cb23-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">smoove</span> genotype <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-d</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-x</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> 1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--name</span> cohort-joint <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--outdir</span> genotyped/ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb23-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--fasta</span> Homo_sapiens_assembly38.fasta <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--vcf</span> cohort.merged.sites.vcf.gz sample1.final.cram</span></code></pre></div></div>
</section>
<section id="vcf-level-qc-bcftools-vcftools-the-daily-driver-tools-for-harmonization-qc" class="level2">
<h2 class="anchored" data-anchor-id="vcf-level-qc-bcftools-vcftools-the-daily-driver-tools-for-harmonization-qc">2.5 VCF-level QC (bcftools + vcftools — the daily-driver tools for harmonization QC)</h2>
<p><strong>What’s happening:</strong> this is sample-level QC done <em>after</em> variant calling rather than on the raw reads — sometimes a sample only reveals a problem once you can see its genotypes in the context of the whole cohort. Per-sample missingness (how many sites failed to get a confident genotype call) flags samples with poor overall data quality. Heterozygosity rate is a classic contamination/inbreeding proxy — unusually high heterozygosity can indicate sample contamination (looks like a mixture of two genomes), unusually low can indicate inbreeding or a technical artifact. Ts/Tv ratio (transition vs transversion substitution rate) has a well-known expected value for real human variation (~2.0-2.1 genome-wide, ~3.0 in exomes) — a callset that deviates substantially is a signal something upstream (often VQSR filtering) went wrong. The KING kinship table detects unexpected relatedness or accidental sample duplicates before they contaminate GWAS results, since undetected relatedness violates the independence assumption most association tests rely on.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb24-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Site-level metrics</span></span>
<span id="cb24-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> stats cohort.final.vcf.gz <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> cohort.stats.txt</span>
<span id="cb24-3"></span>
<span id="cb24-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Per-sample missingness, heterozygosity, Ts/Tv — classic sample-QC exclusion criteria</span></span>
<span id="cb24-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">vcftools</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--gzvcf</span> cohort.final.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--missing-indv</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_qc</span>
<span id="cb24-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">vcftools</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--gzvcf</span> cohort.final.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--het</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_qc</span>
<span id="cb24-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">vcftools</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--gzvcf</span> cohort.final.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--TsTv-summary</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_qc</span>
<span id="cb24-8"></span>
<span id="cb24-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Relatedness / duplicate-sample detection — essential before any GWAS</span></span>
<span id="cb24-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--vcf</span> cohort.final.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-king-table</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_king</span></code></pre></div></div>
<hr>
</section>
</section>
<section id="part-3-harmonization-phasing-imputation-and-building-the-gwas-ready-matrix" class="level1">
<h1>PART 3 — Harmonization, Phasing, Imputation, and Building the GWAS-Ready Matrix</h1>
<section id="normalize-and-harmonize-variant-representation-the-step-everyone-underestimates-left-alignmentnormalization-mismatches-silently-break-joint-analyses-across-cohorts-e.g.-finngen-external-partners" class="level2">
<h2 class="anchored" data-anchor-id="normalize-and-harmonize-variant-representation-the-step-everyone-underestimates-left-alignmentnormalization-mismatches-silently-break-joint-analyses-across-cohorts-e.g.-finngen-external-partners">3.1 Normalize and harmonize variant representation (the step everyone underestimates — left-alignment/normalization mismatches silently break joint analyses across cohorts, e.g.&nbsp;FinnGen + external partners)</h2>
<p><strong>What’s happening:</strong> the same real-world variant can be written multiple equivalent ways in VCF format — a multi-allelic site (one position, several alternate alleles) can be listed as one record or split into several, and indels near repetitive sequence can be left-aligned differently depending on which tool produced the call. If two cohorts represent the identical variant differently, a naive position-based merge will treat them as two different variants and silently lose the overlap. <code>bcftools norm -m -any</code> splits multi-allelic sites into separate biallelic records and left-aligns indels against the reference to a single canonical representation, which is what makes downstream joins across samples, cohorts, and reference panels actually work. The chromosome-naming step handles the other classic mismatch — some tools/panels use <code>chr1</code>, others use <code>1</code> for the same chromosome, and a merge between mismatched naming conventions fails or silently drops everything.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb25-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> norm <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> Homo_sapiens_assembly38.fasta <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-any</span> cohort.final.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-Oz</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> cohort.norm.vcf.gz</span>
<span id="cb25-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> index <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> cohort.norm.vcf.gz</span>
<span id="cb25-3"></span>
<span id="cb25-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Harmonize chromosome naming (chr1 vs 1 — the single most common cross-cohort merge failure)</span></span>
<span id="cb25-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> annotate <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--rename-chrs</span> chr_name_conv.txt cohort.norm.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-Oz</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> cohort.harm.vcf.gz</span></code></pre></div></div>
</section>
<section id="convert-to-plink-format-and-apply-standard-gwas-qc-filters" class="level2">
<h2 class="anchored" data-anchor-id="convert-to-plink-format-and-apply-standard-gwas-qc-filters">3.2 Convert to PLINK format and apply standard GWAS-QC filters</h2>
<p><strong>What’s happening:</strong> PLINK’s binary format (<code>.bed</code>/<code>.bim</code>/<code>.fam</code>) is far more compact and faster to compute on than VCF for the kind of matrix-wide operations GWAS tools need, so this is the standard conversion point. The four filters here are the textbook GWAS quality gates, each guarding against a different failure mode: <code>--geno 0.02</code> drops variants missing genotype calls in &gt;2% of samples (usually a sign the site is technically unreliable, not biologically interesting); <code>--mind 0.02</code> drops <em>samples</em> missing &gt;2% of variants (a poor-quality sample, analogous to the per-sample missingness check in 2.5 but now enforced as a hard exclusion); <code>--maf 0.01</code> drops variants below 1% minor allele frequency, since very rare variants have too little statistical power for standard GWAS and are also where genotyping/calling errors masquerade as “variants” most easily; <code>--hwe 1e-6</code> flags departures from Hardy-Weinberg equilibrium, which in a large random-mating population is often a signal of genotyping error rather than real biology (true selection/population-structure departures exist but are rarer than artifacts at this threshold).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb26-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--vcf</span> cohort.harm.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_plink <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--set-all-var-ids</span> @:#:<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\$</span>r:<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\$</span>a</span>
<span id="cb26-2"></span>
<span id="cb26-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> cohort_plink <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb26-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--geno</span> 0.02 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--mind</span> 0.02 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--maf</span> 0.01 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--hwe</span> 1e-6 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb26-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_qc1</span>
<span id="cb26-6"></span>
<span id="cb26-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># LD-based pruning for PCA/kinship input</span></span>
<span id="cb26-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> cohort_qc1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--indep-pairwise</span> 200 50 0.2 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> prune</span>
<span id="cb26-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> cohort_qc1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--extract</span> prune.prune.in <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_pruned</span></code></pre></div></div>
</section>
<section id="population-structure-and-relatedness-needed-both-for-qc-exclusions-and-as-gwas-covariates" class="level2">
<h2 class="anchored" data-anchor-id="population-structure-and-relatedness-needed-both-for-qc-exclusions-and-as-gwas-covariates">3.3 Population structure and relatedness (needed both for QC exclusions and as GWAS covariates)</h2>
<p><strong>What’s happening:</strong> GWAS association tests assume, at minimum, that samples are unrelated and that allele frequency differences aren’t confounded with the trait through ancestry alone (population stratification — a classic false-positive source where an allele is just more common in one ancestral group that also happens to differ in the trait for unrelated cultural/environmental reasons). KING-robust kinship estimates relatedness directly from genotype sharing patterns in a way that’s robust even in the presence of population structure, letting you catch cryptic relatedness before it inflates your test statistics. PCA on the LD-pruned genotypes captures the main axes of ancestry-driven genetic variation in your cohort; the top PCs get included as covariates in the GWAS model in Part 3.7 specifically to soak up and control for that stratification signal.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb27-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># KING-robust kinship for relatedness/family structure — standard in FinnGen-style pipelines</span></span>
<span id="cb27-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> cohort_pruned <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-king-table</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_kinship</span>
<span id="cb27-3"></span>
<span id="cb27-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># PCA for ancestry / population-stratification covariates</span></span>
<span id="cb27-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> cohort_pruned <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pca</span> 10 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_pca</span></code></pre></div></div>
</section>
<section id="phasing-statistical-reference-based-haplotype-phasing-precursor-to-imputation" class="level2">
<h2 class="anchored" data-anchor-id="phasing-statistical-reference-based-haplotype-phasing-precursor-to-imputation">3.4 Phasing (statistical, reference-based haplotype phasing — precursor to imputation)</h2>
<p><strong>What’s happening:</strong> standard genotyping tells you <em>which two alleles</em> a person carries at each position (e.g.&nbsp;heterozygous A/G) but not <em>which chromosome copy</em> each allele sits on — that’s phase, and imputation algorithms specifically need phased haplotypes to work (they extend known haplotype blocks, not independent genotypes). SHAPEIT4/Eagle2 solve this statistically: given your cohort’s genotypes plus a large reference panel of already-phased haplotypes (the 1000G panel from Part 0), they find the most probable haplotype assignment by looking for chunks of your sample’s genotype pattern that match known haplotype segments in the reference — real chromosomes are mosaics of a surprisingly limited number of ancestral haplotype blocks, which is exactly the structure phasing algorithms exploit.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb28-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># SHAPEIT4 — accurate and fast for large biobank-scale cohorts</span></span>
<span id="cb28-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">shapeit4</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--input</span> cohort_qc1.chr20.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--map</span> genetic_map_chr20.b38.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--region</span> chr20 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--reference</span> 1000GP.chr20.phased.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--output</span> cohort.chr20.phased.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--thread</span> 16</span>
<span id="cb28-8"></span>
<span id="cb28-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Eagle2 is the common alternative, especially paired with Beagle/Minimac imputation pipelines</span></span>
<span id="cb28-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">eagle</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--vcfRef</span> 1000GP.chr20.bcf <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--vcfTarget</span> cohort_qc1.chr20.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--geneticMapFile</span> genetic_map_hg38.txt.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--outPrefix</span> cohort.chr20.eagle_phased <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--numThreads</span> 16</span></code></pre></div></div>
</section>
<section id="imputation-to-a-reference-panel-beagle5-shown-swap-for-minimac4-if-using-the-michigantopmed-panel-conventions" class="level2">
<h2 class="anchored" data-anchor-id="imputation-to-a-reference-panel-beagle5-shown-swap-for-minimac4-if-using-the-michigantopmed-panel-conventions">3.5 Imputation to a reference panel (Beagle5 shown; swap for Minimac4 if using the Michigan/TOPMed panel conventions)</h2>
<p><strong>What’s happening:</strong> your directly-called genotypes cover only the positions your sequencing/calling actually captured well. Imputation fills in genotypes at <em>additional</em> positions present in the (much larger, deeply-sequenced) reference panel, by matching your phased haplotype segments against the panel’s haplotypes and inferring which panel haplotype your sample most likely shares at each additional position — essentially borrowing statistical power from the reference panel’s depth to extend your effective variant coverage far beyond what you directly sequenced. Every imputed genotype comes with an uncertainty estimate (<code>DR2</code>/<code>INFO</code> score — how confidently the algorithm could make that inference), which is why the very next line filters on it: low-confidence imputed calls are worse than not having the variant at all, since they inject noise into a GWAS as if it were real signal.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb29-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">java</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-Xmx32g</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-jar</span> beagle.jar <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb29-2">  gt=cohort.chr20.phased.vcf.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb29-3">  ref=1000GP.chr20.bref3 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb29-4">  map=plink.chr20.GRCh38.map <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb29-5">  out=cohort.chr20.imputed <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb29-6">  nthreads=16</span>
<span id="cb29-7"></span>
<span id="cb29-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Post-imputation QC: filter on imputation INFO score — this threshold is a direct input to your downstream SBayesR/GCTB work</span></span>
<span id="cb29-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> view <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'INFO/DR2&gt;0.8'</span> cohort.chr20.imputed.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-Oz</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> cohort.chr20.imputed.qc.vcf.gz</span></code></pre></div></div>
</section>
<section id="assemble-the-analysis-ready-gwas-matrix" class="level2">
<h2 class="anchored" data-anchor-id="assemble-the-analysis-ready-gwas-matrix">3.6 Assemble the analysis-ready GWAS matrix</h2>
<p><strong>What’s happening:</strong> simple bookkeeping at this point — stitching the per-chromosome imputed files back into one genome-wide dataset and converting to PLINK2’s <code>.pgen</code> format, which stores dosages (fractional genotype probabilities from imputation, not just hard 0/1/2 calls) far more efficiently than VCF at cohort scale. The final MAF filter here is a second, post-imputation pass — imputation itself can introduce very-rare spurious variants at the edges of panel coverage, so re-applying a frequency floor right before association testing is standard practice.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb30-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate imputed chromosomes, convert to PLINK2 pgen for efficient large-scale storage</span></span>
<span id="cb30-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> concat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-Oz</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> cohort.imputed.allchr.vcf.gz cohort.chr<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span>.imputed.qc.vcf.gz</span>
<span id="cb30-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--vcf</span> cohort.imputed.allchr.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-pgen</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_gwas_ready</span>
<span id="cb30-4"></span>
<span id="cb30-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Final MAF/INFO filters typically applied right before association testing</span></span>
<span id="cb30-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pfile</span> cohort_gwas_ready <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--maf</span> 0.01 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-pgen</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_gwas_final</span></code></pre></div></div>
</section>
<section id="run-the-gwas-regenie-the-standard-for-biobank-scale-mixed-model-gwas-handles-related-individuals-and-population-structure-natively" class="level2">
<h2 class="anchored" data-anchor-id="run-the-gwas-regenie-the-standard-for-biobank-scale-mixed-model-gwas-handles-related-individuals-and-population-structure-natively">3.7 Run the GWAS (regenie — the standard for biobank-scale mixed-model GWAS; handles related individuals and population structure natively)</h2>
<p><strong>What’s happening:</strong> naive linear/logistic regression of trait-on-genotype, one variant at a time, breaks down at biobank scale because related individuals and residual population structure inflate false positives (the same confound PCA/kinship in 3.3 partially addresses, but not completely). Regenie’s two-step design handles this more robustly: Step 1 fits a whole-genome ridge regression using directly-genotyped variants to build a polygenic prediction of the trait per individual, which effectively captures and removes the confounding structure (relatedness + polygenic background) before any single-variant test happens. Step 2 then tests each imputed variant for association with the trait <em>residual</em> left after subtracting that Step-1 prediction — dramatically better calibrated than testing raw trait values directly, especially for related samples or rare-variant/case-control-imbalanced traits, which is why <code>--firth</code> (a bias-corrected logistic regression) is included for binary traits.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb31-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Step 1: whole-genome ridge regression on genotyped (not imputed) variants</span></span>
<span id="cb31-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">regenie</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--step</span> 1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bed</span> cohort_qc1 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb31-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--phenoFile</span> pheno.txt <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--covarFile</span> covars_with_PCs.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb31-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bsize</span> 1000 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bt</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_step1</span>
<span id="cb31-5"></span>
<span id="cb31-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Step 2: association testing on imputed dosages</span></span>
<span id="cb31-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">regenie</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--step</span> 2 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pgen</span> cohort_gwas_final <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb31-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--phenoFile</span> pheno.txt <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--covarFile</span> covars_with_PCs.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb31-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bsize</span> 400 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bt</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--firth</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--approx</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb31-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pred</span> cohort_step1_pred.list <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb31-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> cohort_gwas_results</span></code></pre></div></div>
</section>
<section id="where-gctbsbayesr-picks-up-from-here" class="level2">
<h2 class="anchored" data-anchor-id="where-gctbsbayesr-picks-up-from-here">3.8 Where GCTB/SBayesR picks up from here</h2>
<p>The <code>cohort_gwas_results</code> summary statistics (chr, pos, effect allele, beta, se, p, N) plus an LD reference panel built from <code>cohort_pruned</code> (or a matched external panel) are exactly the two inputs your SBayesR workflow expects — same COJO-format conventions you’ve already worked through with GCTB. This is the natural handoff point from “production sequencing pipeline” into the polygenic-score/methods work mentioned as a growth area in the role.</p>
<hr>
</section>
<section id="quick-reference-end-to-end-command-chain-one-sample-condensed" class="level2">
<h2 class="anchored" data-anchor-id="quick-reference-end-to-end-command-chain-one-sample-condensed">Quick reference: end-to-end command chain (one sample, condensed)</h2>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb32-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">fastp</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> R1.fq.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> R2.fq.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> t1.fq.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> t2.fq.gz</span>
<span id="cb32-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bwa-mem2</span> mem <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"@RG\tID:s1\tSM:s1\tPL:ILLUMINA"</span> ref.fa t1.fq.gz t2.fq.gz <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">samtools</span> sort <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> s1.bam <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-</span></span>
<span id="cb32-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> MarkDuplicatesSpark <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> s1.bam <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> s1.dedup.bam</span>
<span id="cb32-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> BaseRecalibrator <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> s1.dedup.bam <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> ref.fa <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--known-sites</span> known.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> recal.table</span>
<span id="cb32-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> ApplyBQSR <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> s1.dedup.bam <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> ref.fa <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bqsr-recal-file</span> recal.table <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> s1.final.bam</span>
<span id="cb32-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> HaplotypeCaller <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-I</span> s1.final.bam <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> ref.fa <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-ERC</span> GVCF <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> s1.g.vcf.gz</span>
<span id="cb32-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> GenomicsDBImport <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--genomicsdb-workspace-path</span> db <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-V</span> s1.g.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-L</span> chr20</span>
<span id="cb32-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> GenotypeGVCFs <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> ref.fa <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-V</span> gendb://db <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> joint.vcf.gz</span>
<span id="cb32-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> VariantRecalibrator ... <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;&amp;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gatk</span> ApplyVQSR ... <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> final.vcf.gz</span>
<span id="cb32-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bcftools</span> norm <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> ref.fa <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-any</span> final.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-Oz</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> norm.vcf.gz</span>
<span id="cb32-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink2</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--vcf</span> norm.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--geno</span> 0.02 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--maf</span> 0.01 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--hwe</span> 1e-6 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> qc</span>
<span id="cb32-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">shapeit4</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--input</span> qc.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--reference</span> ref_panel.vcf.gz <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--output</span> phased.vcf.gz</span>
<span id="cb32-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">beagle</span> gt=phased.vcf.gz ref=panel.bref3 out=imputed</span>
<span id="cb32-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">regenie</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--step</span> 1 ... <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;&amp;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">regenie</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--step</span> 2 ... <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> gwas_results</span></code></pre></div></div>
<hr>
</section>
<section id="whats-deliberately-out-of-scope-here-per-your-ask" class="level2">
<h2 class="anchored" data-anchor-id="whats-deliberately-out-of-scope-here-per-your-ask">What’s deliberately out of scope here (per your ask)</h2>
<ul>
<li>GCP-specific orchestration (Cromwell-on-GCP, Life Sciences API, Terra) — the pipeline above is portable to any of those later; the logic doesn’t change, only the scheduler does</li>
<li>Docker/containerization — swap <code>mamba activate</code> calls for <code>singularity exec</code> if your HPC mandates containers; commands inside stay identical</li>
</ul>
</section>
<section id="challenges-work-through-these-in-order" class="level2">
<h2 class="anchored" data-anchor-id="challenges-work-through-these-in-order">Challenges — work through these in order</h2>
<p><strong>1. Single-sample, single-chromosome, start to finish.</strong> Take GIAB HG002 chr20 FASTQs only (small enough to run on a laptop or one HPC node in under an hour). Run Part 1 end to end. Check <code>samtools flagstat</code> — you should see &gt;99% mapped. Check <code>VerifyBamID2</code> FREEMIX — should be near 0 since it’s a clean reference sample.</p>
<p><strong>2. Validate against truth.</strong> GIAB publishes a high-confidence VCF + BED for HG002. Call variants with HaplotypeCaller on chr20, then run <code>hap.py</code> (Illumina’s benchmarking tool) against the GIAB truth set. Get your precision/recall numbers. This is the single most useful exercise for understanding what “good” variant calling actually looks like — most tutorials skip this step entirely.</p>
<p><strong>3. Break the read group on purpose.</strong> Re-run alignment with a malformed <code>-R</code> string (missing <code>SM</code> tag) and watch HaplotypeCaller fail. Understanding <em>why</em> GATK is strict about read groups will save you hours in production.</p>
<p><strong>4. Trio joint-calling.</strong> Pull HG002/HG003/HG004 (the GIAB Ashkenazi trio), joint-call all three with GenomicsDBImport/GenotypeGVCFs, then run <code>bcftools +mendelian</code> or <code>gatk CalculateGenotypePosteriors</code> to check Mendelian inheritance consistency. Any violations point to either de novo variants or pipeline errors — you’ll need to reason about which.</p>
<p><strong>5. Small-cohort VQSR failure mode.</strong> Try running VariantRecalibrator on just 3-5 samples. It will likely fail or produce garbage tranches — this is expected. Now implement the hard-filtering fallback instead and compare filtered variant counts between the two approaches.</p>
<p><strong>6. Sex-check discrepancy hunt.</strong> Compute chrX/chrY coverage ratios across a batch of samples (real or simulated) and cross-reference against reported sex metadata. Deliberately mislabel one sample and see if your QC catches it.</p>
<p><strong>7. Full chr20-only pipeline through GWAS.</strong> Chain Parts 1→3 on chr20 for ~10-20 samples (mix real GIAB + simulate additional samples by downsampling public 1000G CRAMs). Get all the way to a regenie output file. This is the exercise that actually proves you understand the full chain, not just individual steps.</p>
<p><strong>8. Orchestrate it.</strong> Once each step works manually, wrap the whole chain in Nextflow (<code>nf-core/sarek</code> is the production-grade reference implementation for exactly this pipeline — read its source even if you don’t run it) or Snakemake. This is the actual day-to-day form this work takes in a production setting, not standalone scripts.</p>
<p><strong>9. The hard one — SV/CNV concordance.</strong> Run both Manta and smoove on the same sample, compare their outputs with <code>truvari</code>, and reconcile the discrepancies. SV calling disagreement between callers is normal and understanding <em>why</em> two reasonable tools disagree is a genuinely advanced skill.</p>
<hr>
</section>
<section id="jupyter-notebook-vs-vs-code-which-to-run-this-in" class="level2">
<h2 class="anchored" data-anchor-id="jupyter-notebook-vs-vs-code-which-to-run-this-in">Jupyter Notebook vs VS Code — which to run this in</h2>
<p>Neither is where the <em>pipeline itself</em> should live, and that’s worth being direct about upfront:</p>
<ul>
<li><strong>The core pipeline (Parts 1–3) should be shell scripts or a workflow manager (Snakemake/Nextflow), not notebook cells.</strong> These are long-running, cluster-scheduled, multi-hour-to-multi-day jobs with dependencies between steps. Notebook kernels aren’t built for that — they don’t manage job arrays, don’t handle SLURM dependencies, and a kernel restart or SSH disconnect can silently kill a job that isn’t actually running through the scheduler. Debugging a failed step also gets harder in a notebook, since you lose clean stdout/stderr logs per stage.</li>
<li><strong>VS Code (with the Remote-SSH extension) is the better fit for building and iterating on the pipeline itself</strong> — editing bash/Snakemake/Nextflow files directly on the HPC, using the integrated terminal to submit <code>sbatch</code> jobs, and tailing <code>.log</code>/<code>.out</code> files live. This is genuinely how most people doing this kind of work day-to-day operate.</li>
<li><strong>Jupyter earns its place downstream, not upstream</strong> — for the QC/exploration layer: plotting <code>multiqc</code> output, visualizing PCA/kinship results, inspecting <code>hap.py</code> benchmark tables, plotting Manhattan/QQ plots from your regenie output. That’s real exploratory analysis where cell-by-cell iteration and inline plots genuinely help. Keep it strictly for that layer.</li>
<li>If you want notebook-style reproducibility <em>and</em> proper job control, look at <strong>Papermill</strong> (parameterized notebook execution triggered from a script) or JupyterLab with the SLURM kernel/magic extensions — but even then, treat it as a QC/reporting layer sitting on top of a script-driven pipeline, not the pipeline’s execution engine itself.</li>
</ul>
<p>Practical setup: VS Code Remote-SSH into your HPC login node for all pipeline development and job submission, plus a Jupyter kernel (via <code>srun --pty</code> into a compute node, or JupyterHub if your cluster runs one) purely for the plotting/QC notebooks that consume the pipeline’s outputs.</p>
</section>
<section id="natural-next-study-targets-given-the-jd" class="level2">
<h2 class="anchored" data-anchor-id="natural-next-study-targets-given-the-jd">Natural next study targets given the JD</h2>
<ul>
<li><strong>Long-read/pangenome integration</strong>: minimap2 + PBSV/Sniffles for long-read SV calling, and the pangenome graph tooling (vg, minigraph-cactus) as the field moves off single linear references</li>
<li><strong>Cromwell/WDL or Nextflow</strong> for turning this into a scalable, reproducible workflow — this is likely how “building and maintaining scalable workflows on HPC and cloud” is actually implemented day-to-day</li>
</ul>


</section>
</section>

 ]]></description>
  <category>genomics</category>
  <category>bioinformatics</category>
  <category>GWAS</category>
  <category>tutorial</category>
  <category>HPC</category>
  <guid>https://bntechie.github.io/tutorials/NGS_pipeline_raw_data_to_GWAS/ngs-to-gwas-pipeline.html</guid>
  <pubDate>Thu, 09 Jul 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/NGS_pipeline_raw_data_to_GWAS/images/ngs-to-gwas-pipeline.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>LangChain and Retrieval-Augmented Generation</title>
  <dc:creator>Nivedita </dc:creator>
  <link>https://bntechie.github.io/tutorials/Langchain/langchain-rag-tutorial.html</link>
  <description><![CDATA[ 




<section id="introduction" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="introduction"><span class="header-section-number">1</span> Introduction</h2>
<p>A language model on its own answers from what it learned during training: it has no access to a specific organization’s documents, no memory of earlier turns in a conversation, and no way to call an external tool. LangChain is an open-source framework for closing that gap — it provides standard interfaces for connecting a model to external data, giving it persistent conversational state, and composing several model calls into a single workflow.</p>
<p>This notebook covers LangChain’s core abstractions and Retrieval-Augmented Generation (RAG) computationally, with every code example actually executed rather than described. Two constraints shape how that’s done. First, LangChain moved fast between 2023 and 2025: the framework reached its 1.0 release in October 2025, and several APIs commonly shown in older tutorials — <code>LLMChain</code>, <code>SimpleSequentialChain</code>, <code>SequentialChain</code>, and the classic <code>ConversationBufferMemory</code> family — have since been removed outright, not merely deprecated. This is verified directly below rather than asserted. Second, running real chains against a hosted model requires an API key and network access to that provider, neither of which is assumed here; instead, LangChain’s own deterministic fake models (<code>FakeListLLM</code>, <code>FakeListChatModel</code>) are used where a model call is needed, and a small self-contained retrieval pipeline is built by hand for the RAG section. This keeps every output in this notebook reproducible without external credentials, while the mechanics demonstrated — prompt composition, chaining, memory, and retrieval — are identical to what a real provider integration would do.</p>
</section>
<section id="checking-the-current-langchain-api-before-using-it" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="checking-the-current-langchain-api-before-using-it"><span class="header-section-number">2</span> Checking the Current LangChain API Before Using It</h2>
<p>Before building anything, it’s worth confirming what’s actually available in the installed version, since this determines which patterns below are current and which older material (including common tutorials) would fail outright.</p>
<div id="11c6a152-61c8-41c1-aff7-bf217d9b6e8d" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#pip install langchain langchain-core langgraph numpy</span></span></code></pre></div></div>
</div>
<div id="2405a83a" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> langchain</span>
<span id="cb2-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> langchain_core</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"langchain version:     "</span>, langchain.__version__)</span>
<span id="cb2-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"langchain_core version:"</span>, langchain_core.__version__)</span>
<span id="cb2-6"></span>
<span id="cb2-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The pre-2024 chain and memory classes commonly shown in tutorials</span></span>
<span id="cb2-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> module_name, names <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [</span>
<span id="cb2-9">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"langchain.chains"</span>, [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LLMChain"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SimpleSequentialChain"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SequentialChain"</span>]),</span>
<span id="cb2-10">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"langchain.memory"</span>, [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ConversationBufferMemory"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ConversationSummaryMemory"</span>]),</span>
<span id="cb2-11">]:</span>
<span id="cb2-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb2-13">        mod <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">__import__</span>(module_name, fromlist<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>names)</span>
<span id="cb2-14">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>module_name<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;">: importable"</span>)</span>
<span id="cb2-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ModuleNotFoundError</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb2-16">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>module_name<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;">: NOT importable -&gt; </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>e<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></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>langchain version:      1.3.14
langchain_core version: 1.5.3
langchain.chains: NOT importable -&gt; No module named 'langchain.chains'
langchain.memory: NOT importable -&gt; No module named 'langchain.memory'</code></pre>
</div>
</div>
<p>Both <code>langchain.chains</code> and <code>langchain.memory</code> fail to import in the installed version — these modules were removed, not just deprecated. <code>LLMChain</code> was marked deprecated in LangChain 0.1.17 (April 2024) with removal scheduled for 1.0; <code>ConversationBufferMemory</code> and the related memory classes followed the same path starting in 0.3.1. The 1.0 release (October 2025) carried out that removal. Any code written against these classes — including the pattern shown in older training material on this topic — needs to be rewritten against the current API, which is what the rest of this notebook does.</p>
</section>
<section id="current-architecture" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="current-architecture"><span class="header-section-number">3</span> Current Architecture</h2>
<p>LangChain’s package layout reflects a deliberate split introduced as the framework matured:</p>
<ul>
<li><strong><code>langchain-core</code></strong> — the foundational abstractions: the <code>Runnable</code> interface, prompt templates, output parsers, and the LangChain Expression Language (LCEL), which is the <code>|</code> (pipe) syntax used to compose components.</li>
<li><strong><code>langchain</code></strong> — higher-level, pre-built chains and utilities built on top of <code>langchain-core</code>.</li>
<li><strong><code>langchain-community</code></strong> and provider packages (<code>langchain-openai</code>, <code>langchain-google-genai</code>, and so on) — integrations with specific model providers, vector stores, and document loaders, kept as optional dependencies so a project only installs what it needs.</li>
<li><strong>LangGraph</strong> — a separate, closely integrated framework for stateful, multi-step agent workflows, now the recommended way to build anything involving persistent memory or multi-turn tool use.</li>
</ul>
<p>Every composable piece in this architecture — a prompt, a model, a retriever, an output parser — implements the same <code>Runnable</code> interface, which is why they can all be connected with the same <code>|</code> operator regardless of type. This single unifying abstraction has effectively replaced the older “six components” framing (Model I/O, Data Connection, Chains, Agents, Memory, Callbacks) used in pre-2024 documentation of this framework; the underlying concerns — models, prompts, retrieval, memory, and tool-using agents — are all still present, just organized around Runnables and LCEL rather than as six separate categories.</p>
</section>
<section id="chains" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="chains"><span class="header-section-number">4</span> Chains</h2>
<p>A chain connects a sequence of steps — prompt formatting, a model call, output parsing, possibly a retrieval step — into a single callable pipeline, so an application doesn’t have to manually manage passing state from one step to the next. In the current API, “building a chain” means composing <code>Runnable</code> objects with the <code>|</code> operator; there is no separate <code>Chain</code> class to instantiate for the common cases.</p>
<section id="the-simplest-chain-prompt-to-model-to-parser" class="level3" data-number="4.1">
<h3 data-number="4.1" class="anchored" data-anchor-id="the-simplest-chain-prompt-to-model-to-parser"><span class="header-section-number">4.1</span> The simplest chain: prompt to model to parser</h3>
<p>The most basic pattern takes a prompt template, fills it with a variable, sends it to a model, and extracts the text from the response. Below, <code>FakeListLLM</code> stands in for a real provider – it returns a fixed, pre-specified response regardless of input, which is exactly what makes this reproducible without an API key.</p>
<div id="81615dde" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.prompts <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PromptTemplate</span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.output_parsers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StrOutputParser</span>
<span id="cb4-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.language_models.fake <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> FakeListLLM</span>
<span id="cb4-4"></span>
<span id="cb4-5">llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"GenomeCraft Analytics"</span>])</span>
<span id="cb4-6"></span>
<span id="cb4-7">prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(</span>
<span id="cb4-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What is a good name for a company that makes </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{product}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">?"</span></span>
<span id="cb4-9">)</span>
<span id="cb4-10"></span>
<span id="cb4-11">chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb4-12">result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chain.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"product"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genomics data pipelines"</span>})</span>
<span id="cb4-13"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(result)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>GenomeCraft Analytics</code></pre>
</div>
</div>
</section>
<section id="sequential-composition" class="level3" data-number="4.2">
<h3 data-number="4.2" class="anchored" data-anchor-id="sequential-composition"><span class="header-section-number">4.2</span> Sequential composition</h3>
<p>Where an older API would use <code>SimpleSequentialChain</code> to feed the output of one chain into the next, the current pattern uses <code>RunnablePassthrough.assign()</code> to build a dictionary that carries both the original input and each intermediate result forward.</p>
<div id="de1d6346" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.runnables <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RunnablePassthrough</span>
<span id="cb6-2"></span>
<span id="cb6-3">llm_name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"GenomeCraft Analytics"</span>])</span>
<span id="cb6-4">llm_description <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb6-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GenomeCraft Analytics builds reproducible pipelines for large-scale genomic data processing and interpretation."</span></span>
<span id="cb6-6">])</span>
<span id="cb6-7"></span>
<span id="cb6-8">name_prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(</span>
<span id="cb6-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What is a good name for a company that makes </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{product}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">?"</span></span>
<span id="cb6-10">)</span>
<span id="cb6-11">description_prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(</span>
<span id="cb6-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Write a 20-word description for the company: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{company_name}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb6-13">)</span>
<span id="cb6-14"></span>
<span id="cb6-15">name_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> name_prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> llm_name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb6-16">description_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> description_prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> llm_description <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb6-17"></span>
<span id="cb6-18">overall_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb6-19">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"company_name"</span>: name_chain}</span>
<span id="cb6-20">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> RunnablePassthrough.assign(description<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>description_chain)</span>
<span id="cb6-21">)</span>
<span id="cb6-22"></span>
<span id="cb6-23">result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> overall_chain.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"product"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genomics data pipelines"</span>})</span>
<span id="cb6-24">result</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>{'company_name': 'GenomeCraft Analytics',
 'description': 'GenomeCraft Analytics builds reproducible pipelines for large-scale genomic data processing and interpretation.'}</code></pre>
</div>
</div>
</section>
<section id="multiple-inputs-and-outputs" class="level3" data-number="4.3">
<h3 data-number="4.3" class="anchored" data-anchor-id="multiple-inputs-and-outputs"><span class="header-section-number">4.3</span> Multiple inputs and outputs</h3>
<p>The older <code>SequentialChain</code> class was used when a workflow needed more than one input or output variable, and access to every intermediate result rather than just the final one. The equivalent LCEL pattern nests <code>RunnablePassthrough.assign()</code> calls, so each new field is added to a running dictionary without discarding the earlier ones – this reproduces a four-step translate to summarize to detect-language to follow-up workflow, with all four outputs available at the end.</p>
<div id="2788f312" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">translate_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb8-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The GamersTech laptops impress with their exceptional performance and elegant design."</span></span>
<span id="cb8-3">])</span>
<span id="cb8-4">summarize_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb8-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GamersTech laptops balance strong gaming performance with a sleek, portable design."</span></span>
<span id="cb8-6">])</span>
<span id="cb8-7">language_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"French"</span>])</span>
<span id="cb8-8">followup_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb8-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Merci pour ce retour tres positif sur nos ordinateurs portables GamersTech."</span></span>
<span id="cb8-10">])</span>
<span id="cb8-11"></span>
<span id="cb8-12">review <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb8-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Les ordinateurs portables GamersTech impressionnent par ses performances "</span></span>
<span id="cb8-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"exceptionnelles et son design elegant."</span></span>
<span id="cb8-15">)</span>
<span id="cb8-16"></span>
<span id="cb8-17">translate_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb8-18">    PromptTemplate.from_template(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Translate the following review to English:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{review}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-19">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> translate_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb8-20">)</span>
<span id="cb8-21">summarize_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb8-22">    PromptTemplate.from_template(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Summarize the following review in one sentence:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{english_review}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-23">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> summarize_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb8-24">)</span>
<span id="cb8-25">language_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb8-26">    PromptTemplate.from_template(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What language is the following review written in?</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{review}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-27">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> language_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb8-28">)</span>
<span id="cb8-29">followup_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb8-30">    PromptTemplate.from_template(</span>
<span id="cb8-31">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Write a follow-up response to this summary, in the specified language.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb8-32">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Summary: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{summary}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Language: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{language}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb8-33">    )</span>
<span id="cb8-34">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> followup_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb8-35">)</span>
<span id="cb8-36"></span>
<span id="cb8-37">pipeline <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb8-38">    RunnablePassthrough.assign(english_review<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>translate_chain)</span>
<span id="cb8-39">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> RunnablePassthrough.assign(summary<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>summarize_chain, language<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>language_chain)</span>
<span id="cb8-40">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> RunnablePassthrough.assign(followup_message<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>followup_chain)</span>
<span id="cb8-41">)</span>
<span id="cb8-42"></span>
<span id="cb8-43">output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pipeline.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"review"</span>: review})</span>
<span id="cb8-44"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, value <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> output.items():</span>
<span id="cb8-45">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>key<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="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>value<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>review:
  Les ordinateurs portables GamersTech impressionnent par ses performances exceptionnelles et son design elegant.

english_review:
  The GamersTech laptops impress with their exceptional performance and elegant design.

summary:
  GamersTech laptops balance strong gaming performance with a sleek, portable design.

language:
  French

followup_message:
  Merci pour ce retour tres positif sur nos ordinateurs portables GamersTech.
</code></pre>
</div>
</div>
</section>
<section id="routing-between-sub-chains" class="level3" data-number="4.4">
<h3 data-number="4.4" class="anchored" data-anchor-id="routing-between-sub-chains"><span class="header-section-number">4.4</span> Routing between sub-chains</h3>
<p>A router chain sends an input to one of several specialized sub-chains depending on what kind of input it is – for instance, routing a support query to a billing-specific prompt or a technical-specific prompt. The current equivalent is <code>RunnableBranch</code>, which evaluates a sequence of (condition, chain) pairs and runs the first one that matches.</p>
<div id="b8b88f64" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.runnables <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RunnableBranch</span>
<span id="cb10-2"></span>
<span id="cb10-3">billing_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"This looks like a billing question -- routing to the billing team."</span>])</span>
<span id="cb10-4">technical_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"This looks like a technical question -- routing to the engineering team."</span>])</span>
<span id="cb10-5">general_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"Routing to general support."</span>])</span>
<span id="cb10-6"></span>
<span id="cb10-7">billing_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(<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;">{query}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> billing_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb10-8">technical_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(<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;">{query}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> technical_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb10-9">general_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(<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;">{query}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> general_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb10-10"></span>
<span id="cb10-11">router <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RunnableBranch(</span>
<span id="cb10-12">    (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"invoice"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"charge"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower(), billing_chain),</span>
<span id="cb10-13">    (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"error"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"crash"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower(), technical_chain),</span>
<span id="cb10-14">    general_chain,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default</span></span>
<span id="cb10-15">)</span>
<span id="cb10-16"></span>
<span id="cb10-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> query <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Why was I charged twice on my invoice?"</span>,</span>
<span id="cb10-18">              <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The pipeline crashes with a segmentation fault."</span>,</span>
<span id="cb10-19">              <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What are your support hours?"</span>]:</span>
<span id="cb10-20">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(query, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-&gt;"</span>, router.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>: query}))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Why was I charged twice on my invoice? -&gt; This looks like a billing question -- routing to the billing team.
The pipeline crashes with a segmentation fault. -&gt; This looks like a technical question -- routing to the engineering team.
What are your support hours? -&gt; Routing to general support.</code></pre>
</div>
</div>
</section>
</section>
<section id="memory" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="memory"><span class="header-section-number">5</span> Memory</h2>
<p>A language model call is stateless by default: nothing from one call is automatically available to the next unless it’s explicitly included in the prompt. “Memory” in this context means a mechanism for storing prior turns and re-injecting them, so a conversation feels continuous rather than resetting at every message.</p>
<p>Four memory strategies recur across older LangChain material, distinguished by what they store:</p>
<ul>
<li><strong>Buffer memory</strong> – stores the full conversation verbatim.</li>
<li><strong>Buffer window memory</strong> – stores only the most recent <em>k</em> exchanges, discarding older ones.</li>
<li><strong>Token buffer memory</strong> – keeps as much recent conversation as fits within a token budget, verbatim.</li>
<li><strong>Summary memory</strong> – replaces older turns with a running summary, generated by the model itself.</li>
</ul>
<p>Each represents a different trade-off between fidelity (how much detail is preserved) and cost (how many tokens are spent re-sending history on every call). All four are implemented as classes in <code>langchain.memory</code> in older versions – a module that, as confirmed above, no longer exists in the installed version. The current recommended approach uses LangGraph’s checkpointing system, which persists conversation state outside the chain itself and supports the buffer/window/summary trade-off through how the state is read back rather than through separate classes for each strategy.</p>
<div id="0ca49610" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langgraph.graph <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StateGraph, MessagesState, START, END</span>
<span id="cb12-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langgraph.checkpoint.memory <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> InMemorySaver</span>
<span id="cb12-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.language_models.fake_chat_models <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> FakeListChatModel</span>
<span id="cb12-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.messages <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> HumanMessage</span>
<span id="cb12-5"></span>
<span id="cb12-6">chat_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListChatModel(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb12-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello! It's nice to meet you."</span>,</span>
<span id="cb12-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Your name is Sarah -- you told me a moment ago."</span>,</span>
<span id="cb12-9">])</span>
<span id="cb12-10"></span>
<span id="cb12-11"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> call_model(state: MessagesState):</span>
<span id="cb12-12">    response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chat_model.invoke(state[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"messages"</span>])</span>
<span id="cb12-13">    <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;">"messages"</span>: [response]}</span>
<span id="cb12-14"></span>
<span id="cb12-15">builder <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StateGraph(MessagesState)</span>
<span id="cb12-16">builder.add_node(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model"</span>, call_model)</span>
<span id="cb12-17">builder.add_edge(START, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model"</span>)</span>
<span id="cb12-18">builder.add_edge(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model"</span>, END)</span>
<span id="cb12-19"></span>
<span id="cb12-20">graph <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> builder.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">compile</span>(checkpointer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>InMemorySaver())</span>
<span id="cb12-21">config <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;">"configurable"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"thread_id"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"session-1"</span>}}</span>
<span id="cb12-22"></span>
<span id="cb12-23">turn_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> graph.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"messages"</span>: [HumanMessage(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hi, my name is Sarah."</span>)]}, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>config)</span>
<span id="cb12-24"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Turn 1:"</span>, turn_1[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"messages"</span>][<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>].content)</span>
<span id="cb12-25"></span>
<span id="cb12-26">turn_2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> graph.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"messages"</span>: [HumanMessage(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What is my name?"</span>)]}, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>config)</span>
<span id="cb12-27"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Turn 2:"</span>, turn_2[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"messages"</span>][<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>].content)</span>
<span id="cb12-28"></span>
<span id="cb12-29">persisted_state <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> graph.get_state(config)</span>
<span id="cb12-30"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Messages held in the checkpoint:"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(persisted_state.values[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"messages"</span>]))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Turn 1: Hello! It's nice to meet you.
Turn 2: Your name is Sarah -- you told me a moment ago.

Messages held in the checkpoint: 4</code></pre>
</div>
</div>
<p>The second call correctly answers “Sarah” because the full message history was retrieved from the checkpointer and passed back into the model, not because the fake model has any memory of its own – <code>FakeListChatModel</code> simply returns its next scripted response regardless of input. The <code>thread_id</code> in the config is what scopes the stored history to this particular conversation; a different <code>thread_id</code> would start from empty state.</p>
</section>
<section id="retrieval-augmented-generation-rag" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="retrieval-augmented-generation-rag"><span class="header-section-number">6</span> Retrieval-Augmented Generation (RAG)</h2>
<p>A model’s knowledge is fixed at training time. RAG addresses this by inserting a retrieval step before generation: given a query, first find the most relevant passages from an external document collection, then pass both the query and those passages to the model so its answer is grounded in retrieved material rather than in training data alone.</p>
<p>The pipeline has two stages:</p>
<ol type="1">
<li><strong>Retriever</strong> – converts the query into a vector and finds the most similar vectors in a pre-built index of document chunks.</li>
<li><strong>Generator</strong> – a language model that conditions its answer on both the original query and the retrieved chunks.</li>
</ol>
<p>This addresses three specific weaknesses of using a language model alone: the model’s knowledge can be extended to include material it was never trained on (private documents, content newer than its training cutoff), answers can be traced back to a specific retrieved source, and the retrieval step reduces (though does not eliminate) the tendency to generate a plausible-sounding but unsupported answer.</p>
<section id="common-applications" class="level3" data-number="6.1">
<h3 data-number="6.1" class="anchored" data-anchor-id="common-applications"><span class="header-section-number">6.1</span> Common applications</h3>
<p>RAG is the standard architecture behind several application categories: chatbots that answer from internal company documents, legal or financial Q&amp;A tools that summarize relevant clauses, research assistants that retrieve from academic or clinical literature, and support agents that answer from product documentation.</p>
</section>
</section>
<section id="vector-databases" class="level2" data-number="7">
<h2 data-number="7" class="anchored" data-anchor-id="vector-databases"><span class="header-section-number">7</span> Vector Databases</h2>
<p>A vector database is built to store and search high-dimensional numeric vectors – the embeddings produced by an embedding model – rather than the exact-match or range queries a conventional database is optimized for. Retrieval works by approximate nearest-neighbor search: given a query vector, find the stored vectors closest to it by some distance measure, typically cosine similarity.</p>
<p>Several tools recur in this space, each with a different operating model rather than a strict quality ranking: <strong>Chroma</strong> (lightweight, easy to run locally, common for prototyping), <strong>FAISS</strong> (a similarity-search library rather than a managed database, built for large-scale offline or self-hosted use), <strong>Pinecone</strong> and <strong>Qdrant</strong> (managed or self-hostable services built for production-scale, low-latency search), <strong>Weaviate</strong> (a vector-native database with built-in classification and hybrid search), and <strong>Redis</strong> (a general-purpose store that added vector search as a capability rather than being purpose-built for it). Which one fits a given project depends on scale, latency requirements, and whether self-hosting or a managed service is preferred – not on one being categorically “better” than the others.</p>
</section>
<section id="essential-rag-components-built-by-hand" class="level2" data-number="8">
<h2 data-number="8" class="anchored" data-anchor-id="essential-rag-components-built-by-hand"><span class="header-section-number">8</span> Essential RAG Components, Built by Hand</h2>
<p>The remaining pieces of a RAG pipeline – chunking, embedding, and similarity search – can be demonstrated directly without a hosted embedding model, using term-frequency vectors instead of dense neural embeddings. The mechanics (vectorize each chunk, vectorize the query the same way, rank by cosine similarity) are identical to what a real embedding model does; only the quality of the vectors themselves differs.</p>
<section id="chunking" class="level3" data-number="8.1">
<h3 data-number="8.1" class="anchored" data-anchor-id="chunking"><span class="header-section-number">8.1</span> Chunking</h3>
<p>Long documents are split into smaller pieces before embedding, because a single embedding vector for an entire document would blur together many different topics, making retrieval far less precise. Here, each chunk is already a short single-topic sentence, so this step is trivial – in practice a chunker would split a long document into passages of roughly a few hundred words each, often with a small overlap between consecutive chunks so a sentence spanning a chunk boundary isn’t lost entirely from either side.</p>
<div id="89ef5cce" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">document_chunks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb14-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GWAS identifies associations between genetic variants and traits across the genome."</span>,</span>
<span id="cb14-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fine-mapping narrows a GWAS locus down to the most likely causal variant."</span>,</span>
<span id="cb14-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Polygenic risk scores aggregate many small-effect variants into a single predictive score."</span>,</span>
<span id="cb14-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Retrieval-augmented generation grounds a language model's answer in retrieved documents."</span>,</span>
<span id="cb14-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Vector databases store embeddings and support fast approximate nearest neighbor search."</span>,</span>
<span id="cb14-7">]</span>
<span id="cb14-8">document_chunks</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="8">
<pre><code>['GWAS identifies associations between genetic variants and traits across the genome.',
 'Fine-mapping narrows a GWAS locus down to the most likely causal variant.',
 'Polygenic risk scores aggregate many small-effect variants into a single predictive score.',
 "Retrieval-augmented generation grounds a language model's answer in retrieved documents.",
 'Vector databases store embeddings and support fast approximate nearest neighbor search.']</code></pre>
</div>
</div>
</section>
<section id="a-minimal-embedding-model" class="level3" data-number="8.2">
<h3 data-number="8.2" class="anchored" data-anchor-id="a-minimal-embedding-model"><span class="header-section-number">8.2</span> A minimal embedding model</h3>
<p>Each chunk is converted to a vector using term-frequency counts weighted by inverse document frequency (TF-IDF) – common words shared across every chunk contribute little to the vector, while words distinctive to a particular chunk dominate it. This is a much cruder representation than a trained neural embedding model (it has no notion of synonyms or word order), but the retrieval mechanism built on top of it – cosine similarity ranking – is exactly the same mechanism a production vector database uses on dense embeddings.</p>
<div id="980fff54" class="cell" data-execution_count="9">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><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="cb16-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> re</span>
<span id="cb16-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Counter</span>
<span id="cb16-4"></span>
<span id="cb16-5">STOPWORDS <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;">"a"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"an"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"the"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"is"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"are"</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;">"on"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"of"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"to"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"and"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"or"</span>,</span>
<span id="cb16-6">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"with"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"how"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"does"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"do"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"use"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"s"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"its"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"this"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"that"</span>,</span>
<span id="cb16-7">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"for"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"by"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"into"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"across"</span>}</span>
<span id="cb16-8"></span>
<span id="cb16-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> tokenize(text):</span>
<span id="cb16-10">    tokens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> re.findall(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r"</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[a-z0-9]</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, text.lower())</span>
<span id="cb16-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [t <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tokens <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> STOPWORDS]</span>
<span id="cb16-12"></span>
<span id="cb16-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> build_vocabulary(chunks):</span>
<span id="cb16-14">    vocab <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(tok <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> chunks <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tok <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tokenize(chunk)))</span>
<span id="cb16-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {tok: i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, tok <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;">enumerate</span>(vocab)}</span>
<span id="cb16-16"></span>
<span id="cb16-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> inverse_document_frequency(chunks, vocab):</span>
<span id="cb16-18">    n_chunks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(chunks)</span>
<span id="cb16-19">    doc_freq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.zeros(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(vocab))</span>
<span id="cb16-20">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> chunks:</span>
<span id="cb16-21">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tok <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;">set</span>(tokenize(chunk)):</span>
<span id="cb16-22">            doc_freq[vocab[tok]] <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="cb16-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.log((n_chunks <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="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (doc_freq <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="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="cb16-24"></span>
<span id="cb16-25"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> embed(text, vocab, idf):</span>
<span id="cb16-26">    vec <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.zeros(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(vocab))</span>
<span id="cb16-27">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tok, count <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> Counter(tokenize(text)).items():</span>
<span id="cb16-28">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> tok <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> vocab:</span>
<span id="cb16-29">            vec[vocab[tok]] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> idf[vocab[tok]]</span>
<span id="cb16-30">    norm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.norm(vec)</span>
<span id="cb16-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> vec <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> norm <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> norm <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 class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> vec</span>
<span id="cb16-32"></span>
<span id="cb16-33">vocabulary <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_vocabulary(document_chunks)</span>
<span id="cb16-34">idf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inverse_document_frequency(document_chunks, vocabulary)</span>
<span id="cb16-35">chunk_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [embed(chunk, vocabulary, idf) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> document_chunks]</span>
<span id="cb16-36"></span>
<span id="cb16-37"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Vocabulary size: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(vocabulary)<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>
<span id="cb16-38"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Embedding dimension per chunk: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>chunk_embeddings[<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>shape[<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="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Vocabulary size: 46
Embedding dimension per chunk: 46</code></pre>
</div>
</div>
</section>
<section id="similarity-search" class="level3" data-number="8.3">
<h3 data-number="8.3" class="anchored" data-anchor-id="similarity-search"><span class="header-section-number">8.3</span> Similarity search</h3>
<p>The query is embedded with the same vocabulary and IDF weights, then ranked against every stored chunk by cosine similarity – since both vectors are already normalized to unit length, cosine similarity reduces to a plain dot product.</p>
<div id="05b2730b" class="cell" data-execution_count="10">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> cosine_similarity(a, b):</span>
<span id="cb18-2">    <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.dot(a, b))</span>
<span id="cb18-3"></span>
<span id="cb18-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> retrieve(query, chunks, chunk_embeddings, vocab, idf, top_k<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>
<span id="cb18-5">    query_embedding <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embed(query, vocab, idf)</span>
<span id="cb18-6">    scores <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [cosine_similarity(query_embedding, emb) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> emb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> chunk_embeddings]</span>
<span id="cb18-7">    ranked <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(scores, chunks), reverse<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="cb18-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ranked[:top_k]</span>
<span id="cb18-9"></span>
<span id="cb18-10">query <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;">"How does RAG use a vector database to ground an LLM's answer?"</span></span>
<span id="cb18-11">top_matches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> retrieve(query, document_chunks, chunk_embeddings, vocabulary, idf, top_k<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;">5</span>)</span>
<span id="cb18-12"></span>
<span id="cb18-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> score, chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> top_matches:</span>
<span id="cb18-14">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</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;">:.3f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>chunk<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></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>0.236  Retrieval-augmented generation grounds a language model's answer in retrieved documents.
0.224  Vector databases store embeddings and support fast approximate nearest neighbor search.
0.000  Polygenic risk scores aggregate many small-effect variants into a single predictive score.
0.000  GWAS identifies associations between genetic variants and traits across the genome.
0.000  Fine-mapping narrows a GWAS locus down to the most likely causal variant.</code></pre>
</div>
</div>
<p>The two chunks about RAG and vector databases score well above the three unrelated genetics chunks, which score exactly zero – they share no distinctive vocabulary with the query once stopwords are removed. This is the retrieval step of a RAG pipeline in miniature: the same query-embed-and-rank mechanism, at a scale of five chunks instead of millions, and with TF-IDF vectors standing in for a trained embedding model’s dense vectors.</p>
</section>
<section id="assembling-the-full-pipeline" class="level3" data-number="8.4">
<h3 data-number="8.4" class="anchored" data-anchor-id="assembling-the-full-pipeline"><span class="header-section-number">8.4</span> Assembling the full pipeline</h3>
<p>The retrieved chunks are then handed to a generator, exactly as in the earlier chain examples – a prompt template that includes the retrieved context, piped into a model.</p>
<div id="8f1eb26b" class="cell" data-execution_count="11">
<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">rag_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb20-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RAG grounds an LLM's answer by first retrieving relevant passages -- often from a "</span></span>
<span id="cb20-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vector database using similarity search -- and then conditioning generation on both "</span></span>
<span id="cb20-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"the query and those retrieved passages, rather than relying on the model's training "</span></span>
<span id="cb20-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data alone."</span></span>
<span id="cb20-6">])</span>
<span id="cb20-7"></span>
<span id="cb20-8">rag_prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(</span>
<span id="cb20-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Answer the question using only the context below.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb20-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Context:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{context}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Question: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{question}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb20-11">)</span>
<span id="cb20-12"></span>
<span id="cb20-13">rag_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rag_prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> rag_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb20-14"></span>
<span id="cb20-15">retrieved_context <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;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>.join(chunk <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _, chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> top_matches[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb20-16">answer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rag_chain.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"context"</span>: retrieved_context, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"question"</span>: query})</span>
<span id="cb20-17"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(answer)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>RAG grounds an LLM's answer by first retrieving relevant passages -- often from a vector database using similarity search -- and then conditioning generation on both the query and those retrieved passages, rather than relying on the model's training data alone.</code></pre>
</div>
</div>
</section>
</section>
<section id="best-practices" class="level2" data-number="9">
<h2 data-number="9" class="anchored" data-anchor-id="best-practices"><span class="header-section-number">9</span> Best Practices</h2>
<ul>
<li><strong>Build against LCEL, not the legacy <code>Chain</code> classes.</strong> As demonstrated above, <code>LLMChain</code> and its relatives are gone from the current package, so code written against them fails immediately rather than merely warning.</li>
<li><strong>Choose memory strategy by conversation length and cost, not by default.</strong> Full buffer memory is simplest but grows unbounded; window or summary strategies trade some fidelity for a bounded cost.</li>
<li><strong>Ground factual or domain-specific responses in retrieval.</strong> A RAG step reduces (not eliminates) the risk of a confident, unsupported answer.</li>
<li><strong>Match the vector store to the deployment, not the other way around.</strong> A locally-run prototype and a production service under load have different requirements, and the “best” vector database differs accordingly.</li>
<li><strong>Test each component of a pipeline independently before composing it.</strong> A <code>Runnable</code> can be invoked and inspected on its own before being piped into a longer chain.</li>
<li><strong>Keep prompts concise and retrieval focused.</strong> Retrieving more chunks than the model needs increases cost and can dilute the most relevant context.</li>
<li><strong>Treat this fast-moving ecosystem as fast-moving.</strong> As this notebook’s own deprecation check demonstrates, code and tutorials more than a year or so old are a reasonable place to start but should be verified against the current API before being relied on.</li>
</ul>
</section>
<section id="limitations" class="level2" data-number="10">
<h2 data-number="10" class="anchored" data-anchor-id="limitations"><span class="header-section-number">10</span> Limitations</h2>
<ul>
<li><strong>Retrieval quality bounds answer quality.</strong> A generator conditioned on irrelevant or outdated retrieved chunks will produce a fluent but ungrounded answer regardless of how good the underlying model is.</li>
<li><strong>Full conversation memory has a cost ceiling.</strong> Storing complete history without bound eventually exceeds context limits or becomes prohibitively expensive to resend on every call.</li>
<li><strong>Composed pipelines are harder to test.</strong> A single model call is straightforward to evaluate; a multi-step chain with retrieval, memory, and several model calls has many more places a failure can originate from.</li>
<li><strong>Latency compounds across steps.</strong> Each additional retrieval or model call in a pipeline adds to total response time.</li>
<li><strong>The framework itself changes quickly.</strong> As shown directly above, APIs that were standard as recently as a year or two ago have since been removed, not just superseded – any documentation or tutorial, including this one eventually, is a snapshot rather than a permanent reference.</li>
</ul>
</section>
<section id="summary" class="level2" data-number="11">
<h2 data-number="11" class="anchored" data-anchor-id="summary"><span class="header-section-number">11</span> Summary</h2>
<p>LangChain provides a common <code>Runnable</code> interface – composed with the <code>|</code> operator via LCEL – that unifies prompts, models, retrievers, and output parsers into a single composition system, and this has superseded the older, separate <code>Chain</code> classes (<code>LLMChain</code>, <code>SimpleSequentialChain</code>, <code>SequentialChain</code>) entirely; this notebook confirmed their removal directly rather than assuming it. Memory has undergone the same shift, from the deprecated <code>ConversationBufferMemory</code> family to LangGraph’s checkpointing system, which persists conversation state outside the chain and was demonstrated here with a minimal two-turn example. Retrieval-Augmented Generation was built end-to-end at small scale – chunking, a hand-built TF-IDF embedding, cosine-similarity retrieval, and a generation step conditioned on the retrieved context – which exercises the same retrieve-then-generate mechanism a production system built on a real embedding model and vector database would use, just with a transparent, dependency-free stand-in for the embedding step itself.</p>
</section>
<section id="references" class="level2" data-number="12">
<h2 data-number="12" class="anchored" data-anchor-id="references"><span class="header-section-number">12</span> References</h2>
<ul>
<li>Lewis et al., “Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks” (2020) – <a href="https://arxiv.org/abs/2005.11401">arXiv:2005.11401</a></li>
<li>Karpukhin et al., “Dense Passage Retrieval for Open-Domain Question Answering” (2020) – <a href="https://arxiv.org/abs/2004.04906">arXiv:2004.04906</a></li>
<li>Vaswani et al., “Attention Is All You Need” (2017) – <a href="https://arxiv.org/abs/1706.03762">arXiv:1706.03762</a></li>
<li>Gao et al., “Retrieval-Augmented Generation for Large Language Models: A Survey” (2023) – <a href="https://arxiv.org/abs/2312.10997">arXiv:2312.10997</a></li>
<li>LangChain documentation – <a href="https://docs.langchain.com/">docs.langchain.com</a></li>
</ul>
<blockquote class="blockquote">
<p><strong>A correction to a common citation.</strong> Material on this topic sometimes cites arXiv:2301.12652 as “A Survey on Retrieval-Augmented Generation” by Karpukhin et al.&nbsp;(2023). That identifier actually belongs to a different paper (REPLUG, on retrieval-augmented black-box language models), and Karpukhin et al.’s well-known 2020 paper is on dense passage retrieval, not a RAG survey. The reference list above cites the actual survey (Gao et al., 2023) and the correctly attributed Karpukhin et al.&nbsp;paper separately.</p>
</blockquote>
</section>
<section id="try-it-yourself" class="level2" data-number="13">
<h2 data-number="13" class="anchored" data-anchor-id="try-it-yourself"><span class="header-section-number">13</span> Try It Yourself</h2>
<ol type="1">
<li>Modify the router chain’s conditions so a query containing “refund” is also routed to the billing chain, and confirm the routing with a new test query.</li>
<li>Extend the sequential pipeline (translate to summarize to detect language to follow-up) with a fifth step that scores the summary’s length against a target, reusing the <code>RunnablePassthrough.assign()</code> pattern.</li>
<li>Add two more document chunks to the RAG retrieval example – one relevant to the existing query, one clearly not – and confirm the ranking places them where expected.</li>
<li>Look up LangChain’s current documentation for one component used in this notebook (LCEL, LangGraph checkpointers, or <code>RunnableBranch</code>) and note anything that has changed since this notebook was written.</li>
</ol>
</section>
<section id="solutions" class="level2" data-number="14">
<h2 data-number="14" class="anchored" data-anchor-id="solutions"><span class="header-section-number">14</span> Solutions</h2>
<p>Worked solutions to the four exercises above. Each was run against the same installed LangChain version confirmed at the top of this notebook.</p>
<section id="routing-refund-queries-to-billing" class="level3" data-number="14.1">
<h3 data-number="14.1" class="anchored" data-anchor-id="routing-refund-queries-to-billing"><span class="header-section-number">14.1</span> 1. Routing “refund” queries to billing</h3>
<p>Adding a third <code>or</code> condition to the billing branch’s lambda is enough – no new branch is needed, since a refund question is a billing question.</p>
<div id="cell-32" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.prompts <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PromptTemplate</span>
<span id="cb22-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.output_parsers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StrOutputParser</span>
<span id="cb22-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.language_models.fake <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> FakeListLLM</span>
<span id="cb22-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.runnables <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RunnableBranch</span>
<span id="cb22-5"></span>
<span id="cb22-6">billing_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"This looks like a billing question -- routing to the billing team."</span>])</span>
<span id="cb22-7">technical_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"This looks like a technical question -- routing to the engineering team."</span>])</span>
<span id="cb22-8">general_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"Routing to general support."</span>])</span>
<span id="cb22-9"></span>
<span id="cb22-10">billing_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(<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;">{query}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> billing_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb22-11">technical_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(<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;">{query}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> technical_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb22-12">general_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PromptTemplate.from_template(<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;">{query}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> general_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb22-13"></span>
<span id="cb22-14">router <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RunnableBranch(</span>
<span id="cb22-15">    (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"invoice"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"charge"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"refund"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower(), billing_chain),</span>
<span id="cb22-16">    (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"error"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"crash"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>].lower(), technical_chain),</span>
<span id="cb22-17">    general_chain,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default</span></span>
<span id="cb22-18">)</span>
<span id="cb22-19"></span>
<span id="cb22-20"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> query <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Why was I charged twice on my invoice?"</span>,</span>
<span id="cb22-21">              <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The pipeline crashes with a segmentation fault."</span>,</span>
<span id="cb22-22">              <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What are your support hours?"</span>,</span>
<span id="cb22-23">              <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Can I get a refund for last month's subscription?"</span>]:</span>
<span id="cb22-24">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(query, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-&gt;"</span>, router.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"query"</span>: query}))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Why was I charged twice on my invoice? -&gt; This looks like a billing question -- routing to the billing team.
The pipeline crashes with a segmentation fault. -&gt; This looks like a technical question -- routing to the engineering team.
What are your support hours? -&gt; Routing to general support.
Can I get a refund for last month's subscription? -&gt; This looks like a billing question -- routing to the billing team.</code></pre>
</div>
</div>
<p>The new query about a refund is correctly routed to the billing chain alongside the existing invoice/charge queries.</p>
</section>
<section id="scoring-summary-length-against-a-target" class="level3" data-number="14.2">
<h3 data-number="14.2" class="anchored" data-anchor-id="scoring-summary-length-against-a-target"><span class="header-section-number">14.2</span> 2. Scoring summary length against a target</h3>
<p>A fifth <code>RunnablePassthrough.assign()</code> step adds a <code>length_score</code> field, following the exact pattern the rest of the pipeline already uses – the new step reads <code>summary</code> from the running dictionary and reports how far its word count is from a target.</p>
<div id="cell-35" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.prompts <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PromptTemplate</span>
<span id="cb24-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.output_parsers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StrOutputParser</span>
<span id="cb24-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.language_models.fake <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> FakeListLLM</span>
<span id="cb24-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> langchain_core.runnables <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RunnablePassthrough, RunnableLambda</span>
<span id="cb24-5"></span>
<span id="cb24-6">translate_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb24-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The GamersTech laptops impress with their exceptional performance and elegant design."</span></span>
<span id="cb24-8">])</span>
<span id="cb24-9">summarize_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb24-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GamersTech laptops balance strong gaming performance with a sleek, portable design."</span></span>
<span id="cb24-11">])</span>
<span id="cb24-12">language_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<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;">"French"</span>])</span>
<span id="cb24-13">followup_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FakeListLLM(responses<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb24-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Merci pour ce retour tres positif sur nos ordinateurs portables GamersTech."</span></span>
<span id="cb24-15">])</span>
<span id="cb24-16"></span>
<span id="cb24-17">review <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb24-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Les ordinateurs portables GamersTech impressionnent par ses performances "</span></span>
<span id="cb24-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"exceptionnelles et son design elegant."</span></span>
<span id="cb24-20">)</span>
<span id="cb24-21"></span>
<span id="cb24-22">translate_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb24-23">    PromptTemplate.from_template(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Translate the following review to English:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{review}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb24-24">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> translate_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb24-25">)</span>
<span id="cb24-26">summarize_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb24-27">    PromptTemplate.from_template(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Summarize the following review in one sentence:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{english_review}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb24-28">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> summarize_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb24-29">)</span>
<span id="cb24-30">language_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb24-31">    PromptTemplate.from_template(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What language is the following review written in?</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{review}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb24-32">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> language_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb24-33">)</span>
<span id="cb24-34">followup_chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb24-35">    PromptTemplate.from_template(</span>
<span id="cb24-36">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Write a follow-up response to this summary, in the specified language.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-37">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Summary: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{summary}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Language: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{language}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-38">    )</span>
<span id="cb24-39">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> followup_llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> StrOutputParser()</span>
<span id="cb24-40">)</span>
<span id="cb24-41"></span>
<span id="cb24-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># New fifth step: score the summary's length against a target word count,</span></span>
<span id="cb24-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># reusing the RunnablePassthrough.assign() pattern from the rest of the pipeline.</span></span>
<span id="cb24-44">TARGET_WORDS <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;">12</span></span>
<span id="cb24-45"></span>
<span id="cb24-46"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> score_summary_length(inputs):</span>
<span id="cb24-47">    word_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(inputs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"summary"</span>].split())</span>
<span id="cb24-48">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {</span>
<span id="cb24-49">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"word_count"</span>: word_count,</span>
<span id="cb24-50">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"target_words"</span>: TARGET_WORDS,</span>
<span id="cb24-51">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"delta"</span>: word_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> TARGET_WORDS,</span>
<span id="cb24-52">    }</span>
<span id="cb24-53"></span>
<span id="cb24-54">length_score_step <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RunnableLambda(score_summary_length)</span>
<span id="cb24-55"></span>
<span id="cb24-56">pipeline <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb24-57">    RunnablePassthrough.assign(english_review<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>translate_chain)</span>
<span id="cb24-58">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> RunnablePassthrough.assign(summary<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>summarize_chain, language<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>language_chain)</span>
<span id="cb24-59">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> RunnablePassthrough.assign(followup_message<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>followup_chain)</span>
<span id="cb24-60">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> RunnablePassthrough.assign(length_score<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>length_score_step)</span>
<span id="cb24-61">)</span>
<span id="cb24-62"></span>
<span id="cb24-63">output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pipeline.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"review"</span>: review})</span>
<span id="cb24-64"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, value <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> output.items():</span>
<span id="cb24-65">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>key<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="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>value<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>review:
  Les ordinateurs portables GamersTech impressionnent par ses performances exceptionnelles et son design elegant.

english_review:
  The GamersTech laptops impress with their exceptional performance and elegant design.

summary:
  GamersTech laptops balance strong gaming performance with a sleek, portable design.

language:
  French

followup_message:
  Merci pour ce retour tres positif sur nos ordinateurs portables GamersTech.

length_score:
  {'word_count': 11, 'target_words': 12, 'delta': -1}
</code></pre>
</div>
</div>
<p>The generated summary comes in one word under the 12-word target – <code>delta: -1</code>. All five outputs, including the original input, remain available in the final dictionary, which is the main advantage of the nested-<code>assign()</code> pattern over a plain linear chain.</p>
</section>
<section id="adding-two-more-chunks-to-the-retrieval-example" class="level3" data-number="14.3">
<h3 data-number="14.3" class="anchored" data-anchor-id="adding-two-more-chunks-to-the-retrieval-example"><span class="header-section-number">14.3</span> 3. Adding two more chunks to the retrieval example</h3>
<p>One new chunk is written to be relevant to the existing query (about cosine similarity ranking), and one is written to be clearly unrelated (about heritability, matching the theme of the other irrelevant chunks already in the set).</p>
<div id="cell-38" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1"><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="cb26-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> re</span>
<span id="cb26-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Counter</span>
<span id="cb26-4"></span>
<span id="cb26-5">STOPWORDS <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;">"a"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"an"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"the"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"is"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"are"</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;">"on"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"of"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"to"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"and"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"or"</span>,</span>
<span id="cb26-6">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"with"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"how"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"does"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"do"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"use"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"s"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"its"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"this"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"that"</span>,</span>
<span id="cb26-7">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"for"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"by"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"into"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"across"</span>}</span>
<span id="cb26-8"></span>
<span id="cb26-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> tokenize(text):</span>
<span id="cb26-10">    tokens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> re.findall(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r"</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[a-z0-9]</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, text.lower())</span>
<span id="cb26-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [t <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tokens <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> STOPWORDS]</span>
<span id="cb26-12"></span>
<span id="cb26-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> build_vocabulary(chunks):</span>
<span id="cb26-14">    vocab <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(tok <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> chunks <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tok <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tokenize(chunk)))</span>
<span id="cb26-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {tok: i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, tok <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;">enumerate</span>(vocab)}</span>
<span id="cb26-16"></span>
<span id="cb26-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> inverse_document_frequency(chunks, vocab):</span>
<span id="cb26-18">    n_chunks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(chunks)</span>
<span id="cb26-19">    doc_freq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.zeros(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(vocab))</span>
<span id="cb26-20">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> chunks:</span>
<span id="cb26-21">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tok <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;">set</span>(tokenize(chunk)):</span>
<span id="cb26-22">            doc_freq[vocab[tok]] <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="cb26-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.log((n_chunks <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="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (doc_freq <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="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="cb26-24"></span>
<span id="cb26-25"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> embed(text, vocab, idf):</span>
<span id="cb26-26">    vec <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.zeros(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(vocab))</span>
<span id="cb26-27">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tok, count <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> Counter(tokenize(text)).items():</span>
<span id="cb26-28">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> tok <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> vocab:</span>
<span id="cb26-29">            vec[vocab[tok]] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> idf[vocab[tok]]</span>
<span id="cb26-30">    norm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.norm(vec)</span>
<span id="cb26-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> vec <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> norm <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> norm <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 class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> vec</span>
<span id="cb26-32"></span>
<span id="cb26-33"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> cosine_similarity(a, b):</span>
<span id="cb26-34">    <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.dot(a, b))</span>
<span id="cb26-35"></span>
<span id="cb26-36"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> retrieve(query, chunks, chunk_embeddings, vocab, idf, top_k<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>
<span id="cb26-37">    query_embedding <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embed(query, vocab, idf)</span>
<span id="cb26-38">    scores <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [cosine_similarity(query_embedding, emb) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> emb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> chunk_embeddings]</span>
<span id="cb26-39">    ranked <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(scores, chunks), reverse<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="cb26-40">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ranked[:top_k]</span>
<span id="cb26-41"></span>
<span id="cb26-42">document_chunks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb26-43">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GWAS identifies associations between genetic variants and traits across the genome."</span>,</span>
<span id="cb26-44">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fine-mapping narrows a GWAS locus down to the most likely causal variant."</span>,</span>
<span id="cb26-45">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Polygenic risk scores aggregate many small-effect variants into a single predictive score."</span>,</span>
<span id="cb26-46">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Retrieval-augmented generation grounds a language model's answer in retrieved documents."</span>,</span>
<span id="cb26-47">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Vector databases store embeddings and support fast approximate nearest neighbor search."</span>,</span>
<span id="cb26-48">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># New: one relevant to the query below, one clearly not.</span></span>
<span id="cb26-49">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cosine similarity ranks retrieved chunks by comparing their embedding vectors to the query vector."</span>,</span>
<span id="cb26-50">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heritability partitions phenotypic variance into genetic and environmental components."</span>,</span>
<span id="cb26-51">]</span>
<span id="cb26-52"></span>
<span id="cb26-53">vocabulary <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_vocabulary(document_chunks)</span>
<span id="cb26-54">idf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inverse_document_frequency(document_chunks, vocabulary)</span>
<span id="cb26-55">chunk_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [embed(chunk, vocabulary, idf) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> document_chunks]</span>
<span id="cb26-56"></span>
<span id="cb26-57">query <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;">"How does RAG use a vector database to ground an LLM's answer?"</span></span>
<span id="cb26-58">top_matches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> retrieve(query, document_chunks, chunk_embeddings, vocabulary, idf, top_k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(document_chunks))</span>
<span id="cb26-59"></span>
<span id="cb26-60"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> score, chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> top_matches:</span>
<span id="cb26-61">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</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;">:.3f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>chunk<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></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>0.261  Retrieval-augmented generation grounds a language model's answer in retrieved documents.
0.170  Vector databases store embeddings and support fast approximate nearest neighbor search.
0.165  Cosine similarity ranks retrieved chunks by comparing their embedding vectors to the query vector.
0.000  Polygenic risk scores aggregate many small-effect variants into a single predictive score.
0.000  Heritability partitions phenotypic variance into genetic and environmental components.
0.000  GWAS identifies associations between genetic variants and traits across the genome.
0.000  Fine-mapping narrows a GWAS locus down to the most likely causal variant.</code></pre>
</div>
</div>
<p>The new relevant chunk lands third, just behind the two chunks it shares vocabulary with (“vector”, “database”), and the new irrelevant chunk scores exactly zero alongside the other genetics chunks, since it shares no non-stopword vocabulary with the query. The ranking places both new chunks exactly where expected.</p>
</section>
<section id="whats-changed-in-the-current-documentation" class="level3" data-number="14.4">
<h3 data-number="14.4" class="anchored" data-anchor-id="whats-changed-in-the-current-documentation"><span class="header-section-number">14.4</span> 4. What’s changed in the current documentation</h3>
<p>Checked two components used in this notebook against LangChain’s current reference docs:</p>
<ul>
<li><strong><code>RunnableBranch</code></strong> is unchanged. The current reference lists it as available since v0.1 with no deprecation notice, so the routing pattern used above is still the recommended one, not a stopgap.</li>
<li><strong>LangGraph checkpointing</strong> has grown a companion concept since this notebook’s core pattern was written. The current persistence docs now distinguish two systems: checkpointers (like <code>InMemorySaver</code>, used above) for short-term, thread-scoped memory, and a separate <code>Store</code> (for example <code>InMemoryStore</code>) for long-term, cross-thread memory such as user preferences or facts that should persist beyond a single conversation thread. The docs also now explicitly flag <code>InMemorySaver</code> as suitable for debugging and testing only, recommending <code>PostgresSaver</code> for production use, a distinction not called out above.</li>
</ul>
<p>For the two-turn example in this notebook, both points are consistent with what’s shown – <code>InMemorySaver</code> is exactly right for a scoped, in-memory demo, and there was no cross-thread memory need that would have called for a <code>Store</code>.</p>


</section>
</section>

 ]]></description>
  <guid>https://bntechie.github.io/tutorials/Langchain/langchain-rag-tutorial.html</guid>
  <pubDate>Sat, 04 Jul 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/Langchain/images/langchain-rag-pipeline.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Twins, Variance, and the Logic of Heritability</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/twin_heritability/twin_heritability_tutorial.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/twin_heritability/images/ace-twin-model.svg" alt="Path diagram of the ACE twin model: latent factors A (genetic), C (shared environment), and E (unique environment) connecting to Twin 1 and Twin 2, with A shared 100% in MZ twins and 50% in DZ twins" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The one fact this whole tutorial runs on: MZ and DZ twins share C and E equally, but differ in exactly how much of A they share – which is enough, on its own, to separate genetic from environmental variance.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">Heritability</span> <span class="tag">ACE Model</span> <span class="tag">Twin Studies</span> <span class="tag">R</span></p>
</div>
<p>Why do some siblings look and behave almost identically, while others in the same family seem to have little in common?</p>
<p>Height, cognitive ability, disease risk — nearly every measurable human trait varies from person to person.</p>
<blockquote class="blockquote">
<p>How much of that variation comes from genetic differences, and how much comes from the environment people happen to grow up in?</p>
</blockquote>
<p>That question is what <strong>heritability</strong> tries to answer. This tutorial builds the idea up from scratch: what heritability actually means, why twins are uniquely suited to estimate it, how that logic becomes a fitted statistical model, and how the same idea extends beyond twins to unrelated people using DNA directly.</p>
<section id="heritability-is-a-statement-about-variance-not-about-you" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="heritability-is-a-statement-about-variance-not-about-you"><span class="header-section-number">1</span> Heritability Is a Statement About Variance, Not About You</h2>
<p>A heritability of 70% does <strong>not</strong> mean 70% of your height is genetic.</p>
<blockquote class="blockquote">
<p>Heritability describes how much of the <em>variation across a population</em> is attributable to genetic differences. It says nothing about any one individual.</p>
</blockquote>
<p>Phenotypic variance splits into two pieces:</p>
<p><img src="https://latex.codecogs.com/png.latex?V_P%20=%20V_G%20+%20V_E"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?V_P"> is the total observed variance in a trait, <img src="https://latex.codecogs.com/png.latex?V_G"> is the share attributable to genetic differences between people, and <img src="https://latex.codecogs.com/png.latex?V_E"> is the share attributable to environmental differences.</p>
<p>Heritability is simply the genetic fraction of that total:</p>
<p><img src="https://latex.codecogs.com/png.latex?h%5E2%20=%20%5Cfrac%7BV_G%7D%7BV_P%7D,%20%5Cqquad%200%20%5Cle%20h%5E2%20%5Cle%201"></p>
<p>A trait can be highly heritable and still change dramatically across generations. Human height sits around <img src="https://latex.codecogs.com/png.latex?h%5E2%20%5Capprox%200.8">, yet average height rose substantially over the 20th century as nutrition and healthcare improved. High heritability describes <em>current</em> variance, not <em>future</em> immutability — and it is specific to the population it was measured in. A population with little environmental variation will show a higher <img src="https://latex.codecogs.com/png.latex?h%5E2"> than one with large environmental disparities, for the exact same trait and the exact same genetics, simply because <img src="https://latex.codecogs.com/png.latex?V_E"> differs between them.</p>
</section>
<section id="why-twins-are-a-natural-experiment" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="why-twins-are-a-natural-experiment"><span class="header-section-number">2</span> Why Twins Are a Natural Experiment</h2>
<p>Directly separating <img src="https://latex.codecogs.com/png.latex?V_G"> from <img src="https://latex.codecogs.com/png.latex?V_E"> in an ordinary sample is impossible — you never observe the same person raised in two different genetic or environmental worlds.</p>
<p>Twins offer a workaround, because two twin types differ in exactly one respect.</p>
<pre><code>Monozygotic (MZ) twins  →  share ~100% of their segregating genetic variants
Dizygotic (DZ) twins    →  share ~50% of their segregating genetic variants, on average</code></pre>
<p>Both twin types, raised together, are assumed to share their rearing environment equally.</p>
<p>If a trait is influenced by genetics, MZ twins — who share all their genes — should resemble each other more closely than DZ twins, who share only half. The <em>size</em> of that gap between MZ and DZ similarity is where an estimate of heritability comes from.</p>
</section>
<section id="from-twin-correlations-to-variance-components" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="from-twin-correlations-to-variance-components"><span class="header-section-number">3</span> From Twin Correlations to Variance Components</h2>
<p>Twin models split phenotypic variance into three parts rather than two:</p>
<p><img src="https://latex.codecogs.com/png.latex?V_P%20=%20A%20+%20C%20+%20E"></p>
<pre><code>A  =  additive genetic variance        (variants add up across the genome)
C  =  shared (common) environment      (identical for both twins in a pair)
E   =  unique environment               (everything that differs within a pair,
                                          including measurement error)</code></pre>
<p>Given the sharing rules above, the expected correlation between twins works out to:</p>
<p><img src="https://latex.codecogs.com/png.latex?r_%7BMZ%7D%20=%20A%20+%20C"> <img src="https://latex.codecogs.com/png.latex?r_%7BDZ%7D%20=%20%5Ctfrac%7B1%7D%7B2%7DA%20+%20C"></p>
<p>(All variances here are on the standardized scale, so <img src="https://latex.codecogs.com/png.latex?A%20+%20C%20+%20E%20=%201">.)</p>
<p>Two equations, two unknowns — the difference between them isolates <img src="https://latex.codecogs.com/png.latex?A"> directly.</p>
</section>
<section id="falconers-method" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="falconers-method"><span class="header-section-number">4</span> Falconer’s Method</h2>
<p>Subtracting the two correlation equations gives a strikingly simple estimator, due to Falconer (1960):</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Chat%7BA%7D%20=%202(r_%7BMZ%7D%20-%20r_%7BDZ%7D)"> <img src="https://latex.codecogs.com/png.latex?%5Chat%7BC%7D%20=%20r_%7BMZ%7D%20-%20%5Chat%7BA%7D"> <img src="https://latex.codecogs.com/png.latex?%5Chat%7BE%7D%20=%201%20-%20r_%7BMZ%7D"></p>
<p>No model-fitting software required — just two correlations and arithmetic. Let’s simulate twin data with known true variance components and check whether this recovers them.</p>
<div id="5ae96590" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:36:05.190800Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:36:05.179472Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:36:05.406893Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:36:05.400705Z&quot;}}" data-execution_count="1">
<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">simulate_twins <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, a, c, e, shared_genetic_fraction) {</span>
<span id="cb3-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a, c, e are given as SDs; shared_genetic_fraction = 1 for MZ, 0.5 for DZ</span></span>
<span id="cb3-3">  A_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;">rnorm</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, a)</span>
<span id="cb3-4">  A1_unique <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</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;">sqrt</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> shared_genetic_fraction))</span>
<span id="cb3-5">  A2_unique <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</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;">sqrt</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> shared_genetic_fraction))</span>
<span id="cb3-6">  A1 <span class="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>(shared_genetic_fraction) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> A_shared <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> A1_unique</span>
<span id="cb3-7">  A2 <span class="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>(shared_genetic_fraction) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> A_shared <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> A2_unique</span>
<span id="cb3-8"></span>
<span id="cb3-9">  C_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;">rnorm</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, c)</span>
<span id="cb3-10">  E1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, e)</span>
<span id="cb3-11">  E2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, e)</span>
<span id="cb3-12"></span>
<span id="cb3-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;">twin1 =</span> A1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> C_shared <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> E1, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">twin2 =</span> A2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> C_shared <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> E2)</span>
<span id="cb3-14">}</span>
<span id="cb3-15"></span>
<span id="cb3-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;">1</span>)</span>
<span id="cb3-17">n_pairs <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;">2000</span></span>
<span id="cb3-18">a2_true <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.50</span>; c2_true <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.20</span>; e2_true <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.30</span>    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># must sum to 1</span></span>
<span id="cb3-19">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;">sqrt</span>(a2_true); c <span class="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>(c2_true); 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;">sqrt</span>(e2_true)</span>
<span id="cb3-20"></span>
<span id="cb3-21">mz <span class="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_twins</span>(n_pairs, a, c, e, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shared_genetic_fraction =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>)</span>
<span id="cb3-22">dz <span class="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_twins</span>(n_pairs, a, c, e, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shared_genetic_fraction =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb3-23"></span>
<span id="cb3-24">r_mz <span class="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>(mz<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>twin1, mz<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>twin2)</span>
<span id="cb3-25">r_dz <span class="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>(dz<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>twin1, dz<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>twin2)</span>
<span id="cb3-26"></span>
<span id="cb3-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</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;">"MZ correlation: %.3f</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>, r_mz))</span>
<span id="cb3-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</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;">"DZ correlation: %.3f</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>, r_dz))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>MZ correlation: 0.708
DZ correlation: 0.439</code></pre>
</div>
</div>
<div id="916d9eb6" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:36:05.510203Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:36:05.419662Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:36:05.541020Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:36:05.539254Z&quot;}}" data-execution_count="2">
<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">h2_falconer <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> (r_mz <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> r_dz)</span>
<span id="cb5-2">c2_falconer <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> r_mz <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> h2_falconer</span>
<span id="cb5-3">e2_falconer <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> r_mz</span>
<span id="cb5-4"></span>
<span id="cb5-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb5-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">component =</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 (genetic)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"C (shared env)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"E (unique env)"</span>),</span>
<span id="cb5-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">true_value =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(a2_true, c2_true, e2_true),</span>
<span id="cb5-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">falconer_estimate =</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;">c</span>(h2_falconer, c2_falconer, e2_falconer), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb5-9">)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 3 × 3</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">component</th>
<th data-quarto-table-cell-role="th" scope="col">true_value</th>
<th data-quarto-table-cell-role="th" scope="col">falconer_estimate</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>A (genetic)</td>
<td>0.5</td>
<td>0.538</td>
</tr>
<tr class="even">
<td>C (shared env)</td>
<td>0.2</td>
<td>0.170</td>
</tr>
<tr class="odd">
<td>E (unique env)</td>
<td>0.3</td>
<td>0.292</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Falconer’s arithmetic recovers all three true values closely, using nothing more than two correlations.</p>
<p>That simplicity is also its ceiling. Falconer’s method gives no standard errors, no way to test whether <img src="https://latex.codecogs.com/png.latex?C"> is actually needed at all, and no way to compare competing models formally. For that, twin research moved to full likelihood-based modeling — the same logic, expressed as a fitted statistical model instead of a shortcut formula.</p>
</section>
<section id="why-move-to-a-fitted-model" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="why-move-to-a-fitted-model"><span class="header-section-number">5</span> Why Move to a Fitted Model?</h2>
<p>Falconer’s estimator is a fixed, one-shot calculation. A <strong>structural equation model (SEM)</strong> treats <img src="https://latex.codecogs.com/png.latex?A">, <img src="https://latex.codecogs.com/png.latex?C">, and <img src="https://latex.codecogs.com/png.latex?E"> as parameters to be <em>estimated by maximum likelihood</em>, given the raw twin data and the covariance structure implied by MZ/DZ sharing:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5CSigma_%7BMZ%7D%20=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%20A%20+%20C%20%5C%5C%20A%20+%20C%20&amp;%201%20%5Cend%7Bpmatrix%7D,%20%5Cqquad%0A%5CSigma_%7BDZ%7D%20=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%20%5Ctfrac%7B1%7D%7B2%7DA%20+%20C%20%5C%5C%20%5Ctfrac%7B1%7D%7B2%7DA%20+%20C%20&amp;%201%20%5Cend%7Bpmatrix%7D"></p>
<p>Fitting these by likelihood, rather than reading them off two correlations, buys three things at once: standard errors on <img src="https://latex.codecogs.com/png.latex?A">, <img src="https://latex.codecogs.com/png.latex?C">, and <img src="https://latex.codecogs.com/png.latex?E">; the ability to constrain <img src="https://latex.codecogs.com/png.latex?C=0"> or <img src="https://latex.codecogs.com/png.latex?A=0"> and formally test whether that constrained model fits significantly worse; and a natural way to add covariates or handle missing data. This is exactly what dedicated twin-modeling software like OpenMx does under the hood — the version below implements the same likelihood directly, so the mechanics stay visible.</p>
<div id="8cd875e1" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:36:05.545294Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:36:05.544310Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:36:05.556231Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:36:05.554566Z&quot;}}" data-execution_count="3">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Bivariate normal log-likelihood for a set of twin pairs, given a 2x2 covariance matrix (mean 0)</span></span>
<span id="cb6-2">biv_normal_loglik <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>(dat, Sigma) {</span>
<span id="cb6-3">  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;">nrow</span>(dat)</span>
<span id="cb6-4">  detS <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> Sigma[<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>Sigma[<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;">2</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> Sigma[<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="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-5">  Sinv <span class="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;">c</span>(Sigma[<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;">2</span>], <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>Sigma[<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="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>Sigma[<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>], Sigma[<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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</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> detS</span>
<span id="cb6-6">  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.matrix</span>(dat)</span>
<span id="cb6-7">  quad <span class="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>((x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> Sinv) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb6-8">  <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> 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;">log</span>(detS) <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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(quad) <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="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="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>pi)</span>
<span id="cb6-9">}</span>
<span id="cb6-10"></span>
<span id="cb6-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Negative log-likelihood for the ACE model (and constrained sub-models)</span></span>
<span id="cb6-12">neg_ll_ACE <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>(par, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fix_c =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fix_a =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>) {</span>
<span id="cb6-13">  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;">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.na</span>(fix_a)) fix_a <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;">plogis</span>(par[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb6-14">  c2 <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> (<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>(fix_c)) fix_c <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;">plogis</span>(par[<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> a2)</span>
<span id="cb6-15">  e2 <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> a2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> c2</span>
<span id="cb6-16">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (e2 <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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e10</span>)</span>
<span id="cb6-17"></span>
<span id="cb6-18">  Sigma_mz <span class="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;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, a2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c2, a2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c2, <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;">2</span>)</span>
<span id="cb6-19">  Sigma_dz <span class="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;">c</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.5</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>a2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c2, <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>a2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c2, <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;">2</span>)</span>
<span id="cb6-20"></span>
<span id="cb6-21">  <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;">biv_normal_loglik</span>(mz, Sigma_mz) <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;">biv_normal_loglik</span>(dz, Sigma_dz))</span>
<span id="cb6-22">}</span></code></pre></div></div>
</div>
<section id="fitting-ace-ae-and-ce" class="level3" data-number="5.1">
<h3 data-number="5.1" class="anchored" data-anchor-id="fitting-ace-ae-and-ce"><span class="header-section-number">5.1</span> Fitting ACE, AE, and CE</h3>
<p>Three models, nested inside each other: the full ACE model, and two restricted versions that force one component to zero.</p>
<div id="3d7f649b" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:36:05.560341Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:36:05.559080Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:36:05.737490Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:36:05.735538Z&quot;}}" data-execution_count="4">
<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">fit_ACE <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-2">  opt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optim</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;">0</span>), neg_ll_ACE, <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;">"Nelder-Mead"</span>)</span>
<span id="cb7-3">  a2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plogis</span>(opt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>par[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]); c2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plogis</span>(opt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>par[<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> a2); e2 <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> a2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> c2</span>
<span id="cb7-4">  <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;">a2 =</span> a2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c2 =</span> c2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">e2 =</span> e2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">negLL =</span> opt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb7-5">}</span>
<span id="cb7-6"></span>
<span id="cb7-7">fit_AE <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-8">  f <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>(par) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">neg_ll_ACE</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(par[<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;">1e6</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fix_c =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb7-9">  opt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optim</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, f, <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;">"Brent"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lower =</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;">10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">upper =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb7-10">  a2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plogis</span>(opt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>par[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]); e2 <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> a2</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;">a2 =</span> a2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c2 =</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;">e2 =</span> e2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">negLL =</span> opt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb7-12">}</span>
<span id="cb7-13"></span>
<span id="cb7-14">fit_CE <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-15">  f <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>(par) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">neg_ll_ACE</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="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e6</span>, par[<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;">fix_a =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb7-16">  opt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optim</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, f, <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;">"Brent"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lower =</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;">10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">upper =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb7-17">  c2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plogis</span>(opt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>par[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]); e2 <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> c2</span>
<span id="cb7-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;">a2 =</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;">c2 =</span> c2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">e2 =</span> e2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">negLL =</span> opt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb7-19">}</span>
<span id="cb7-20"></span>
<span id="cb7-21">ace <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fit_ACE</span>(); ae <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fit_AE</span>(); ce <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fit_CE</span>()</span>
<span id="cb7-22"></span>
<span id="cb7-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb7-24">  <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;">"ACE"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AE"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CE"</span>),</span>
<span id="cb7-25">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">a2 =</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;">c</span>(ace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>a2, ae<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>a2, ce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>a2), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb7-26">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c2 =</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;">c</span>(ace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c2, ae<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c2, ce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c2), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb7-27">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">e2 =</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;">c</span>(ace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>e2, ae<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>e2, ce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>e2), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb7-28">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">neg2LL =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</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;">c</span>(ace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>negLL, ae<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>negLL, ce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>negLL), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb7-29">)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 3 × 5</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">model</th>
<th data-quarto-table-cell-role="th" scope="col">a2</th>
<th data-quarto-table-cell-role="th" scope="col">c2</th>
<th data-quarto-table-cell-role="th" scope="col">e2</th>
<th data-quarto-table-cell-role="th" scope="col">neg2LL</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ACE</td>
<td>0.508</td>
<td>0.190</td>
<td>0.301</td>
<td>20975.0</td>
</tr>
<tr class="even">
<td>AE</td>
<td>0.709</td>
<td>0.000</td>
<td>0.291</td>
<td>21001.4</td>
</tr>
<tr class="odd">
<td>CE</td>
<td>0.000</td>
<td>0.574</td>
<td>0.426</td>
<td>21173.7</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The full ACE fit lands almost exactly on the true simulated values (0.50 / 0.20 / 0.30) — maximum likelihood recovers the same answer Falconer’s shortcut did, as it should when the model is correctly specified.</p>
<p>Dropping <img src="https://latex.codecogs.com/png.latex?C"> (the AE model) doesn’t just zero it out — the genetic component <img src="https://latex.codecogs.com/png.latex?%5Chat%20A"> jumps up to absorb the shared-environment variance that’s no longer available to explain the resemblance between twins. That’s a useful diagnostic on its own: watch what happens to the <em>other</em> components when you force one to zero.</p>
</section>
<section id="is-the-extra-complexity-of-ace-actually-justified" class="level3" data-number="5.2">
<h3 data-number="5.2" class="anchored" data-anchor-id="is-the-extra-complexity-of-ace-actually-justified"><span class="header-section-number">5.2</span> Is the Extra Complexity of ACE Actually Justified?</h3>
<p>A likelihood ratio test answers this directly: is the improvement in fit from adding <img src="https://latex.codecogs.com/png.latex?C"> back in bigger than you’d expect from noise alone?</p>
<div id="84e38a67" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:36:05.742148Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:36:05.740346Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:36:05.764616Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:36:05.762810Z&quot;}}" data-execution_count="5">
<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">lrt_stat <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> ae<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>negLL <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> ace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>negLL</span>
<span id="cb8-2">lrt_df   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> ae<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df</span>
<span id="cb8-3">lrt_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 class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pchisq</span>(lrt_stat, lrt_df)</span>
<span id="cb8-4"></span>
<span id="cb8-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</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;">"LRT comparing AE against full ACE: chi-sq = %.2f, df = %d, p = %.5f</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>,</span>
<span id="cb8-6">            lrt_stat, lrt_df, lrt_p))</span>
<span id="cb8-7"></span>
<span id="cb8-8">aic <span class="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;">ACE =</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>ace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>negLL <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>ace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df,</span>
<span id="cb8-9">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">AE  =</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>ae<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>negLL  <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>ae<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df,</span>
<span id="cb8-10">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">CE  =</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>ce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>negLL  <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>ce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df)</span>
<span id="cb8-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">AIC by model (lower is better):</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>)</span>
<span id="cb8-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(aic, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>LRT comparing AE against full ACE: chi-sq = 26.37, df = 1, p = 0.00000

AIC by model (lower is better):
    ACE      AE      CE 
20981.0 21005.4 21177.7 </code></pre>
</div>
</div>
<p>Both diagnostics agree: forcing <img src="https://latex.codecogs.com/png.latex?C"> to zero makes the model fit significantly worse, and AIC prefers the full ACE model over either restricted alternative. In a real analysis, this is exactly the workflow — fit the full model and each restriction, then let the likelihood ratio test and AIC decide which components the data actually support, rather than assuming a particular model in advance.</p>
<p>This is the concrete payoff of moving from Falconer’s formula to a fitted model: a formal, quantitative answer to “does shared environment matter here?” — not just a point estimate.</p>
</section>
</section>
<section id="beyond-twins-heritability-from-unrelated-people" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="beyond-twins-heritability-from-unrelated-people"><span class="header-section-number">6</span> Beyond Twins: Heritability From Unrelated People</h2>
<p>Twin models lean on a pair of fixed relatedness values — MZ pairs share (on average) all their genetic variance, DZ pairs share half. Modern genomics can go further: instead of assuming relatedness from pedigree structure, measure it directly from genotypes at hundreds of thousands of SNPs, for people who aren’t related at all.</p>
<p>The genetic relationship matrix (GRM) between two individuals <img src="https://latex.codecogs.com/png.latex?i"> and <img src="https://latex.codecogs.com/png.latex?j">, using standardized genotypes, is:</p>
<p><img src="https://latex.codecogs.com/png.latex?GRM_%7Bij%7D%20=%20%5Cfrac%7B1%7D%7BM%7D%5Csum_%7Bk=1%7D%5E%7BM%7D%20%5Ctilde%7Bx%7D_%7Bik%7D%5C,%20%5Ctilde%7Bx%7D_%7Bjk%7D"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?M"> is the number of SNPs and <img src="https://latex.codecogs.com/png.latex?%5Ctilde%20x"> denotes a genotype standardized to mean 0 and variance 1. Full siblings average close to 0.5 here, just like the pedigree expectation for DZ twins — but now it’s measured, not assumed, and it varies continuously even among people with no known family relationship at all.</p>
<p>The <strong>Haseman–Elston regression</strong> (Haseman and Elston 1972) turns this into a heritability estimate with a beautifully simple idea:</p>
<blockquote class="blockquote">
<p>Pairs of people who are more genetically similar should also be more phenotypically similar — in direct proportion to how related they are.</p>
</blockquote>
<p>Regressing pairwise phenotypic similarity on GRM values, the slope of that line is an estimate of SNP heritability. This is the logic that underlies GREML and GCTA (Yang et al.&nbsp;2010) applied at genome-wide scale — the toy version below applies it to a small simulated cohort of <em>unrelated</em> individuals.</p>
<div id="12aef535" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:36:05.768650Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:36:05.767210Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:36:06.195246Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:36:06.193849Z&quot;}}" data-execution_count="6">
<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;">2</span>)</span>
<span id="cb10-2">n_ind <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;">300</span></span>
<span id="cb10-3">n_snps <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;">2000</span></span>
<span id="cb10-4">maf <span class="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>(n_snps, <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.5</span>)</span>
<span id="cb10-5"></span>
<span id="cb10-6">genotypes <span class="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>(maf, <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;">rbinom</span>(n_ind, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, p))</span>
<span id="cb10-7">geno_std  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(genotypes)                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># standardize each SNP column</span></span>
<span id="cb10-8">GRM       <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (geno_std <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>(geno_std)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_snps</span>
<span id="cb10-9"></span>
<span id="cb10-10">h2_true <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="cb10-11">genetic_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;">rnorm</span>(n_snps, <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;">sqrt</span>(h2_true <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_snps))</span>
<span id="cb10-12">genetic_component  <span class="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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(geno_std <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> genetic_effect)) <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>(h2_true)</span>
<span id="cb10-13">env_component      <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_ind, <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;">sqrt</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> h2_true))</span>
<span id="cb10-14">phenotype          <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> genetic_component <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> env_component</span>
<span id="cb10-15"></span>
<span id="cb10-16">pheno_outer <span class="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>(phenotype, phenotype)</span>
<span id="cb10-17">idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">upper.tri</span>(GRM)</span>
<span id="cb10-18"></span>
<span id="cb10-19">he_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;">lm</span>(pheno_outer[idx] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> GRM[idx])</span>
<span id="cb10-20"><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;">coef</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(he_fit)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 2 × 4 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">Estimate</th>
<th data-quarto-table-cell-role="th" scope="col">Std. Error</th>
<th data-quarto-table-cell-role="th" scope="col">t value</th>
<th data-quarto-table-cell-role="th" scope="col">Pr(&gt;|t|)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">(Intercept)</th>
<td>-0.0008</td>
<td>0.0043</td>
<td>-0.1892</td>
<td>0.8499</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">GRM[idx]</th>
<td>0.6392</td>
<td>0.1922</td>
<td>3.3250</td>
<td>0.0009</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The regression slope — the Haseman–Elston estimate of SNP heritability — lands in the right neighborhood of the true value of 0.5, estimated entirely from unrelated individuals and their genotypes, with no twins or known family structure anywhere in sight.</p>
<p>This is the same conceptual move that let human genetics scale heritability estimation from small twin registries to biobanks of hundreds of thousands of unrelated people (Yang et al.&nbsp;2010) — replace an assumed relatedness value (0, 0.5, or 1, from pedigree structure) with a measured one (any value in between, from genotypes), and the same regression logic still applies.</p>
</section>
<section id="key-takeaways" class="level2" data-number="7">
<h2 data-number="7" class="anchored" data-anchor-id="key-takeaways"><span class="header-section-number">7</span> Key Takeaways</h2>
<ul>
<li>Heritability describes variance across a population, not a property of any one person, and it changes with the population’s environmental context.</li>
<li>Twin designs work because MZ and DZ pairs differ in exactly one thing — how much genetic variance they share — while (by assumption) sharing their environment equally.</li>
<li>Falconer’s method turns two correlations into estimates of A, C, and E with simple arithmetic, and recovers the truth well in simulation.</li>
<li>A fitted SEM (the ACE model) reproduces Falconer’s estimates while adding what arithmetic alone can’t: standard errors, and formal likelihood ratio / AIC comparisons between nested models like ACE, AE, and CE.</li>
<li>The same logic extends past twins entirely — the Haseman–Elston regression estimates heritability from measured genetic relatedness (a GRM) among people who share no known family relationship at all.</li>
</ul>
</section>
<section id="references" class="level2" data-number="8">
<h2 data-number="8" class="anchored" data-anchor-id="references"><span class="header-section-number">8</span> References</h2>
<p>Falconer, D. S. (1960). <em>Introduction to Quantitative Genetics.</em> Oliver and Boyd.</p>
<p>Neale, M. C., &amp; Cardon, L. R. (1992). <em>Methodology for Genetic Studies of Twins and Families.</em> Kluwer Academic Publishers.</p>
<p>Haseman, J. K., &amp; Elston, R. C. (1972). The investigation of linkage between a quantitative trait and a marker locus. <em>Behavior Genetics</em>, 2(1), 3–19.</p>
<p>Yang, J., Benyamin, B., McEvoy, B. P., Gordon, S., Henders, A. K., Nyholt, D. R., Madden, P. A., Heath, A. C., Martin, N. G., Montgomery, G. W., Goddard, M. E., &amp; Visscher, P. M. (2010). Common SNPs explain a large proportion of the heritability for human height. <em>Nature Genetics</em>, 42(7), 565–569.</p>
<p>Polderman, T. J. C., Benyamin, B., de Leeuw, C. A., Sullivan, P. F., van Bochoven, A., Visscher, P. M., &amp; Posthuma, D. (2015). Meta-analysis of the heritability of human traits based on fifty years of twin studies. <em>Nature Genetics</em>, 47(7), 702–709.</p>


</section>

 ]]></description>
  <category>Statistical Genetics</category>
  <category>Quantitative Genetics</category>
  <category>Twin Studies</category>
  <category>Heritability</category>
  <guid>https://bntechie.github.io/tutorials/twin_heritability/twin_heritability_tutorial.html</guid>
  <pubDate>Sun, 21 Jun 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/twin_heritability/images/ace-twin-model.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Genetic Association Testing for Rare Variants</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/rare_variants/rare_variant_tutorial.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/rare_variants/images/rare-variant-tests.svg" alt="A 12-variant gene track, colored by true effect direction, branching into a burden test that cancels the mixed effects out (p = 0.46) and a SKAT test that recovers the signal (p = 0.011)" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The tutorial’s central result in one picture: the same 12-variant gene, with the same causal architecture, gives two completely different answers depending on whether the test sums effects (burden) or sums their squares (SKAT).</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">SKAT</span> <span class="tag">Burden Test</span> <span class="tag">Rare Variants</span> <span class="tag">R</span></p>
</div>
<p>Rare variants are, by definition, seen in only a handful of people. That single fact breaks almost every assumption a standard GWAS relies on, and it forces a completely different statistical toolkit.</p>
<p>This tutorial builds that toolkit from the ground up. We start with why single-variant testing fails, work through burden tests and SKAT by deriving their score statistics by hand, and finish with the saddlepoint approximation that makes rare-variant testing usable at biobank scale. Every statistic below is implemented in base R and checked against either a built-in R function or a Monte Carlo simulation.</p>
<section id="why-single-variant-tests-fail-for-rare-variants" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Why Single-Variant Tests Fail for Rare Variants</h1>
<blockquote class="blockquote">
<p><strong>If GWAS works for common variants, why not just run the same test on rare ones?</strong> Because you’ll rarely even observe the variant. A single-variant test needs carriers in your sample before it can say anything at all.</p>
</blockquote>
<p>Large-effect variants on protein function are disproportionately rare, because natural selection removes them from the population before they become common. This is the central reason rare variants matter: the alleles most likely to have a real, interpretable effect on a trait are exactly the ones a standard genotyping array will barely capture.</p>
<p>The scale of the problem is easiest to see through a simple question: how many people do you need before you’re likely to observe even one carrier?</p>
<section id="how-many-samples-until-you-see-one-copy" class="level2" data-number="1.1">
<h2 data-number="1.1" class="anchored" data-anchor-id="how-many-samples-until-you-see-one-copy"><span class="header-section-number">1.1</span> 1.1 How many samples until you see one copy?</h2>
<p>Assume random mating, so the two chromosomes carried by each of <img src="https://latex.codecogs.com/png.latex?N"> individuals are independent draws with minor allele frequency <img src="https://latex.codecogs.com/png.latex?p">. The probability of seeing <strong>zero</strong> copies of the variant is <img src="https://latex.codecogs.com/png.latex?(1-p)%5E%7B2N%7D">, so:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(%5Ctext%7Bat%20least%20one%20copy%7D)%20=%201%20-%20(1-p)%5E%7B2N%7D%20%3E%200.999%20%5Cquad%5CLongrightarrow%5Cquad%20N%20%3E%20%5Cfrac%7B%5Clog(0.001)%7D%7B2%5Clog(1-p)%7D%0A"></p>
<div id="94e57a14" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:30.272059Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:30.262033Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:30.388837Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:30.382518Z&quot;}}" data-execution_count="1">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample size needed to observe &gt;= 1 copy of a variant with 99.9% probability</span></span>
<span id="cb1-2">maf <span class="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.01</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0001</span>)</span>
<span id="cb1-3">required_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;">log</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</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;">log</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> maf))</span>
<span id="cb1-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;">MAF =</span> maf, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Required_N =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ceiling</span>(required_n))</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 4 × 2</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">MAF</th>
<th data-quarto-table-cell-role="th" scope="col">Required_N</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1e-01</td>
<td>33</td>
</tr>
<tr class="even">
<td>1e-02</td>
<td>344</td>
</tr>
<tr class="odd">
<td>1e-03</td>
<td>3453</td>
</tr>
<tr class="even">
<td>1e-04</td>
<td>34538</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Going from a MAF of 1% to 0.01% multiplies the required sample size a hundredfold. Single-variant testing simply runs out of carriers long before it runs out of interesting biology. And yet rare variants are collectively far from rare: each person carries roughly 200 rare coding variants, so a gene-level view of these variants is both necessary and has plenty of signal to work with.</p>
</section>
</section>
<section id="collapsing-variants-into-a-gene-level-burden" class="level1" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Collapsing Variants Into a Gene-Level Burden</h1>
<blockquote class="blockquote">
<p><strong>If no single variant has enough carriers, what do we test instead?</strong> We stop asking about one variant and start asking about a gene. Define a carrier as anyone with at least one rare variant in the region, and test whether carriers and non-carriers differ in disease risk.</p>
</blockquote>
<p>This converts a sparse, high-dimensional problem (many rare variants, few carriers each) into a simple 2x2 question: <strong>are carriers more likely to be cases than non-carriers?</strong></p>
<div id="f318aeb9" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:30.487052Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:30.398354Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:30.573211Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:30.567904Z&quot;}}" data-execution_count="2">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># A toy burden contingency table: carriers of a rare-variant burden vs disease status</span></span>
<span id="cb2-2">burden_table <span class="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;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</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;">5</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;">nrow =</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;">byrow =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb2-3">                       <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="at" style="color: #657422;
background-color: null;
font-style: inherit;">Status =</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;">"Case"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Control"</span>),</span>
<span id="cb2-4">                                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Burden  =</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;">"Carrier"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Non-carrier"</span>)))</span>
<span id="cb2-5">burden_table</span>
<span id="cb2-6"></span>
<span id="cb2-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fisher.test</span>(burden_table)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 2 × 2 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">Carrier</th>
<th data-quarto-table-cell-role="th" scope="col">Non-carrier</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">Case</th>
<td>14</td>
<td>6</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">Control</th>
<td>5</td>
<td>15</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<pre><code>
    Fisher's Exact Test for Count Data

data:  burden_table
p-value = 0.01039
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
  1.457116 35.737819
sample estimates:
odds ratio 
  6.614723 </code></pre>
</div>
</div>
<p>The odds ratio of association follows directly from the table:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7BOR%7D%20=%20%5Cfrac%7Ba/c%7D%7Bb/d%7D%20=%20%5Cfrac%7Bad%7D%7Bbc%7D%0A"></p>
<p>With small carrier counts, a chi-squared test is unreliable, so <code>fisher.test</code> reaches for the exact hypergeometric distribution instead of a large-sample approximation. It’s worth confirming exactly what that function is computing.</p>
</section>
<section id="fishers-exact-test-from-first-principles" class="level1" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> Fisher’s Exact Test, From First Principles</h1>
<blockquote class="blockquote">
<p><strong>What is <code>fisher.test</code> actually computing under the hood?</strong> The exact probability of observing a table at least as extreme as yours, conditional on the row and column totals staying fixed, under the hypergeometric distribution.</p>
</blockquote>
<p>For a 2x2 table with cell counts <img src="https://latex.codecogs.com/png.latex?a,%20b,%20c,%20d">, the probability of the observed table conditional on its margins is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP%20=%20%5Cfrac%7B%5Cbinom%7Ba+b%7D%7Ba%7D%5Cbinom%7Bc+d%7D%7Bc%7D%7D%7B%5Cbinom%7Bn%7D%7Ba+c%7D%7D%0A"></p>
<p>The two-sided p-value sums this probability over every table with the same margins that is <strong>at least as unlikely</strong> as the one observed — not just the fraction for the observed table alone.</p>
<div id="2eab5ccc" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:30.585603Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:30.583962Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:30.621924Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:30.620115Z&quot;}}" data-execution_count="3">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Verify the hypergeometric formula by hand against R's Fisher test</span></span>
<span id="cb4-2">a <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;">14</span>; b <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>; c <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>; d <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;">15</span></span>
<span id="cb4-3">row1 <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> b; row2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> d</span>
<span id="cb4-4">col1 <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> c; col2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> b <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> d</span>
<span id="cb4-5">total <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> row1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> row2</span>
<span id="cb4-6"></span>
<span id="cb4-7">p_observed <span class="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>(row1, 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;">choose</span>(row2, 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;">choose</span>(total, col1)</span>
<span id="cb4-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"P(observed table) ="</span>, p_observed, <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>)</span>
<span id="cb4-9"></span>
<span id="cb4-10">possible_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;">max</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, col1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> row2)<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;">min</span>(row1, col1)</span>
<span id="cb4-11">probs <span class="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>(possible_a, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) {</span>
<span id="cb4-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">choose</span>(row1, 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;">choose</span>(row2, col1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</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;">choose</span>(total, col1)</span>
<span id="cb4-13">})</span>
<span id="cb4-14">p_two_sided <span class="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>(probs[probs <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> p_observed <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-8</span>])</span>
<span id="cb4-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Two-sided p-value (by hand) ="</span>, p_two_sided, <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>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>P(observed table) = 0.004577422 
Two-sided p-value (by hand) = 0.0103867 </code></pre>
</div>
</div>
<p>0.0104 matches R’s reported 0.01039 to rounding. This is a useful sanity check to run once: it confirms <code>fisher.test</code> isn’t summing probabilities for tables that happen to be less extreme in only one direction, a mistake that’s easy to make when re-implementing exact tests by hand.</p>
<p>R.A. Fisher, who introduced this test alongside the concept of the null hypothesis, was explicit that a null hypothesis can only ever be rejected by data, never confirmed by it — a framing worth keeping in mind for every p-value that follows.</p>
<p>A single 2x2 table is a fine illustration, but it throws away information: every rare variant gets collapsed into one indicator, regardless of how rare it individually is, and regardless of whether its effect on the trait is protective or damaging. A regression framework fixes both problems.</p>
</section>
<section id="a-regression-framework-for-burden-testing" class="level1" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> A Regression Framework for Burden Testing</h1>
<p>For a continuous trait, the natural model regresses the phenotype on every rare variant in the region:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY%20=%20X%5Calpha%20+%20G_1%5Cbeta_1%20+%20G_2%5Cbeta_2%20+%20%5Cdots%20+%20G_q%5Cbeta_q%20+%20%5Cvarepsilon,%20%5Cqquad%20H_0:%20%5Cbeta_1%20=%20%5Cdots%20=%20%5Cbeta_q%20=%200%0A"></p>
<p>For a binary trait, the same idea holds on the log-odds scale:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7Blogit%7D(%5Cpi)%20=%20%5Clog%5Cleft(%5Cfrac%7B%5Cpi%7D%7B1-%5Cpi%7D%5Cright)%20=%20X%5Calpha%20+%20G_1%5Cbeta_1%20+%20%5Cdots%20+%20G_q%5Cbeta_q%0A"></p>
<p>Testing <img src="https://latex.codecogs.com/png.latex?q"> separate coefficients still burns degrees of freedom and statistical power. The burden test collapses them into a single weighted sum:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7Blogit%7D(%5Cpi)%20=%20X%5Calpha%20+%20%5Cbeta_c%5Cleft(w_1%20G_1%20+%20w_2%20G_2%20+%20%5Cdots%20+%20w_q%20G_q%5Cright)%0A"></p>
<blockquote class="blockquote">
<p><strong>Why weight variants at all, rather than just summing raw genotype counts?</strong> Because not every rare variant is equally rare. A weighting scheme that upweights rarer variants reflects the prior belief that rarer variants are more likely to be under stronger negative selection, and therefore more likely to matter.</p>
</blockquote>
<p>A common choice, due to Wu et al.&nbsp;(2011), is <img src="https://latex.codecogs.com/png.latex?w_j%20%5Csim%20%5Ctext%7BBeta%7D(%5Ctext%7BMAF%7D_j;%201,%2025)">, which assigns steeply increasing weight as MAF approaches zero.</p>
</section>
<section id="simulating-a-rare-variant-test-gene" class="level1" data-number="5">
<h1 data-number="5"><span class="header-section-number">5</span> Simulating a Rare-Variant Test Gene</h1>
<p>To make the rest of this tutorial concrete, we simulate a 12-variant gene in 4,000 individuals: four variants that increase disease risk, two that are protective, and six with no effect at all. This bidirectional architecture — some variants increase risk, others decrease it — is deliberately chosen, because it’s the setting where burden and variance-component tests are expected to behave differently.</p>
<div id="fbc47627" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:30.626512Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:30.624873Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:30.678684Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:30.676727Z&quot;}}" data-execution_count="4">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>)</span>
<span id="cb6-2"></span>
<span id="cb6-3">n <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>                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sample size</span></span>
<span id="cb6-4">q <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;">12</span>                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of rare variants in the gene</span></span>
<span id="cb6-5">maf <span class="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>(q, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">min =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0005</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.01</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># rare variant MAFs</span></span>
<span id="cb6-6"></span>
<span id="cb6-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Genotype matrix: 0/1/2 copies of the minor allele, drawn under Hardy-Weinberg</span></span>
<span id="cb6-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;">sapply</span>(maf, <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;">rbinom</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, p))</span>
<span id="cb6-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(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;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"v"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(q))</span>
<span id="cb6-10"></span>
<span id="cb6-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># One covariate (e.g. a normalized age term)</span></span>
<span id="cb6-12">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;">cbind</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;">scale</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n)))</span>
<span id="cb6-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</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;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Intercept"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Covariate"</span>)</span>
<span id="cb6-14"></span>
<span id="cb6-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Causal architecture: variants 1-4 increase risk, variants 5-6 are protective,</span></span>
<span id="cb6-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the remaining 6 are non-causal noise. Effects are deliberately bidirectional,</span></span>
<span id="cb6-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a setting where burden tests are known to lose power.</span></span>
<span id="cb6-18">true_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;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.3</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="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 class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.4</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;">1.2</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>, q <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>
<span id="cb6-19"></span>
<span id="cb6-20">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;">c</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;">2.2</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;"># covariate effects under the null model of disease risk</span></span>
<span id="cb6-21">linpred <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> X <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> alpha <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> true_beta</span>
<span id="cb6-22">pi_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;">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="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>linpred))</span>
<span id="cb6-23">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;">rbinom</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, pi_true)</span>
<span id="cb6-24"></span>
<span id="cb6-25"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cases:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(y), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" Controls:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</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 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>)</span>
<span id="cb6-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MAFs:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(maf, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb6-27"></span>
<span id="cb6-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">saveRDS</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;">G =</span> G, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">X =</span> X, <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;">maf =</span> maf, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">true_beta =</span> true_beta),</span>
<span id="cb6-29">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sim_data.rds"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Cases: 408  Controls: 3592 
MAFs: 0.0071 0.0058 0.0018 0.0032 0.0058 7e-04 0.0049 0.0087 0.0029 0.006 6e-04 0.0071 </code></pre>
</div>
</div>
<p>A roughly 1:9 case-to-control ratio, which is typical of a moderately prevalent disease in a biobank cohort. This imbalance will matter a great deal later on.</p>
<p>With the gene simulated, we can now compute the Wu weight for each variant from its true MAF.</p>
<div id="73d20b9b" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:30.683134Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:30.681512Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:30.709686Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:30.708048Z&quot;}}" data-execution_count="5">
<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">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;">readRDS</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sim_data.rds"</span>)</span>
<span id="cb8-2">maf <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>maf</span>
<span id="cb8-3"></span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Wu weights: w_j = Beta density of MAF under Beta(1, 25), upweighting rarer variants</span></span>
<span id="cb8-5">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;">dbeta</span>(maf, <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;">25</span>)</span>
<span id="cb8-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;">variant =</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>G), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MAF =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(maf, <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;">weight =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(w, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 12 × 3</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">variant</th>
<th data-quarto-table-cell-role="th" scope="col">MAF</th>
<th data-quarto-table-cell-role="th" scope="col">weight</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>v1</td>
<td>0.0071</td>
<td>21.05</td>
</tr>
<tr class="even">
<td>v2</td>
<td>0.0058</td>
<td>21.75</td>
</tr>
<tr class="odd">
<td>v3</td>
<td>0.0018</td>
<td>23.92</td>
</tr>
<tr class="even">
<td>v4</td>
<td>0.0032</td>
<td>23.14</td>
</tr>
<tr class="odd">
<td>v5</td>
<td>0.0058</td>
<td>21.76</td>
</tr>
<tr class="even">
<td>v6</td>
<td>0.0007</td>
<td>24.56</td>
</tr>
<tr class="odd">
<td>v7</td>
<td>0.0049</td>
<td>22.20</td>
</tr>
<tr class="even">
<td>v8</td>
<td>0.0087</td>
<td>20.28</td>
</tr>
<tr class="odd">
<td>v9</td>
<td>0.0029</td>
<td>23.32</td>
</tr>
<tr class="even">
<td>v10</td>
<td>0.0060</td>
<td>21.63</td>
</tr>
<tr class="odd">
<td>v11</td>
<td>0.0006</td>
<td>24.67</td>
</tr>
<tr class="even">
<td>v12</td>
<td>0.0071</td>
<td>21.08</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The rarest variant here (v11, MAF = 0.0006) gets almost 25% more weight than the most common one in the set (v8, MAF = 0.0087). This is a modest difference at these MAFs, but the gap widens sharply as MAF approaches the lower end of the exome-wide spectrum.</p>
</section>
<section id="three-classical-tests-and-why-genetics-prefers-one-of-them" class="level1" data-number="6">
<h1 data-number="6"><span class="header-section-number">6</span> Three Classical Tests, and Why Genetics Prefers One of Them</h1>
<p>Testing whether <img src="https://latex.codecogs.com/png.latex?%5Cbeta_c%20%5Cneq%200"> in a maximum-likelihood framework can be done three ways:</p>
<ul>
<li><strong>Wald test</strong>: fit the full (alternative) model, and measure how far the estimated effect is from zero, scaled by its standard error.</li>
<li><strong>Likelihood ratio test (LRT)</strong>: fit both the null and alternative models, and measure the drop in log-likelihood between them.</li>
<li><strong>Score test</strong>: fit only the null model, and evaluate the gradient of the log-likelihood at that null.</li>
</ul>
<p>All three measure the same underlying distance between the null hypothesis and the maximum-likelihood estimate, just along different geometric axes. As sample size grows, they converge to the same <img src="https://latex.codecogs.com/png.latex?%5Cchi%5E2_1"> distribution:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AT_%7B%5Ctext%7BWald%7D%7D%20%5Capprox%20T_%7B%5Ctext%7BLRT%7D%7D%20%5Capprox%20T_%7B%5Ctext%7BScore%7D%7D%20%5Csim%20%5Cchi%5E2_1%0A"></p>
<blockquote class="blockquote">
<p><strong>If they’re asymptotically the same, why does the choice matter for rare-variant testing?</strong> Computation. A modern biobank study tests tens of thousands of genes, often under a mixed model that corrects for relatedness and population structure. Fitting the full alternative model separately for every gene is computationally intractable. The score test only requires fitting the null model <em>once</em> — testing each gene afterward is just matrix multiplication against a fixed set of residuals.</p>
</blockquote>
<p>This is the entire reason burden tests, SKAT, and SKAT-O are all built as score tests rather than Wald or LRT tests.</p>
</section>
<section id="deriving-the-burden-score-statistic" class="level1" data-number="7">
<h1 data-number="7"><span class="header-section-number">7</span> Deriving the Burden Score Statistic</h1>
<p>Recall the weighted burden model, with burden score <img src="https://latex.codecogs.com/png.latex?B_i%20=%20%5Csum_j%20w_j%20g_%7Bi,j%7D"> for individual <img src="https://latex.codecogs.com/png.latex?i">:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7Blogit%7D(%5Cpi_i)%20=%20X_i%5Calpha%20+%20%5Cbeta_c%20B_i,%20%5Cqquad%20l%20%5Cpropto%20%5Csum_i%20%5Cleft%5By_i%20%5Clog(%5Cpi_i)%20+%20(1-y_i)%5Clog(1-%5Cpi_i)%5Cright%5D%0A"></p>
<p>The score function is the gradient of the log-likelihood with respect to <img src="https://latex.codecogs.com/png.latex?%5Cbeta_c">. By the chain rule:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cpartial%20l_i%7D%7B%5Cpartial%20%5Cbeta_c%7D%20=%20%5Cfrac%7B%5Cpartial%20l_i%7D%7B%5Cpartial%20%5Cpi_i%7D%5Ccdot%5Cfrac%7B%5Cpartial%20%5Cpi_i%7D%7B%5Cpartial%20%5Ceta_i%7D%5Ccdot%5Cfrac%7B%5Cpartial%20%5Ceta_i%7D%7B%5Cpartial%20%5Cbeta_c%7D%0A=%20%5Cleft%5B%5Cfrac%7By_i%20-%20%5Cpi_i%7D%7B%5Cpi_i(1-%5Cpi_i)%7D%5Cright%5D%5Cleft%5B%5Cpi_i(1-%5Cpi_i)%5Cright%5D%5Cleft%5BB_i%5Cright%5D%20=%20(y_i%20-%20%5Cpi_i)B_i%0A"></p>
<p>The <img src="https://latex.codecogs.com/png.latex?%5Cpi_i(1-%5Cpi_i)"> terms cancel exactly, which is why the score function has such a clean form. Evaluated at the null (<img src="https://latex.codecogs.com/png.latex?%5Cbeta_c%20=%200">, so <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> is replaced by its null-model prediction <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cpi_i">):</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AU(0)%20=%20%5Csum_i%20(y_i%20-%20%5Chat%5Cpi_i)B_i%20=%20%5Csum_i%20(y_i%20-%20%5Chat%5Cpi_i)%5Csum_j%20w_j%20g_%7Bi,j%7D%0A"></p>
<p>Squaring gives the burden test statistic used in tools like SAIGE-GENE:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AQ_B%20=%20U(0)%5E2%20=%20%5Cleft%5B%5Csum_i%20(y_i-%5Chat%5Cpi_i)%5Csum_j%20w_j%20g_%7Bi,j%7D%5Cright%5D%5E2%0A"></p>
<p>Intuitively: <img src="https://latex.codecogs.com/png.latex?U(0)"> is large whenever people who carry more of the weighted burden also have larger-than-expected residuals — i.e., the gene’s cumulative dosage tracks disease status.</p>
</section>
<section id="testing-the-burden-model-in-r" class="level1" data-number="8">
<h1 data-number="8"><span class="header-section-number">8</span> Testing the Burden Model in R</h1>
<p>We fit the null model once (covariates only), compute residuals, and turn the derivation above directly into code.</p>
<div id="a92644d8" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:30.714637Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:30.712908Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:30.914666Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:30.912520Z&quot;}}" data-execution_count="6">
<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">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;">readRDS</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sim_data.rds"</span>)</span>
<span id="cb9-2">G <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>G; X <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>X; 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; maf <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>maf</span>
<span id="cb9-3">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;">dbeta</span>(maf, <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;">25</span>)</span>
<span id="cb9-4"></span>
<span id="cb9-5"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 1: fit the null model (covariates only, no genotypes) ---</span></span>
<span id="cb9-6">null_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;">glm</span>(y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> X[, <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;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">binomial</span>())</span>
<span id="cb9-7">pi_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;">fitted</span>(null_model)</span>
<span id="cb9-8">resid  <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> pi_hat</span>
<span id="cb9-9"></span>
<span id="cb9-10"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 2: build the weighted burden score B_i = sum_j w_j * G_ij ---</span></span>
<span id="cb9-11">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.vector</span>(G <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> w)</span>
<span id="cb9-12"></span>
<span id="cb9-13"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 3: burden score statistic U(0) = sum_i resid_i * B_i ---</span></span>
<span id="cb9-14">U0 <span class="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>(resid <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> B)</span>
<span id="cb9-15"></span>
<span id="cb9-16"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 4: variance of U(0) under the null ---</span></span>
<span id="cb9-17"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Var(U) = B' V B, where V = diag(pi_hat * (1 - pi_hat))</span></span>
<span id="cb9-18">V <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pi_hat <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> pi_hat)</span>
<span id="cb9-19">var_U0 <span class="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>(V <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> B<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="cb9-20"></span>
<span id="cb9-21"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 5: score test statistic and p-value ---</span></span>
<span id="cb9-22">Q_burden <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> U0<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> var_U0</span>
<span id="cb9-23">p_burden_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;">pchisq</span>(Q_burden, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</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;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb9-24"></span>
<span id="cb9-25"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Burden score U(0)      :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(U0, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Var[U(0)]              :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(var_U0, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Burden score statistic :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(Q_burden, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Burden score p-value   :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p_burden_score, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-29"></span>
<span id="cb9-30"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Compare to a Wald test from a direct logistic regression on the burden score ---</span></span>
<span id="cb9-31">alt_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;">glm</span>(y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> X[, <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> B, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">binomial</span>())</span>
<span id="cb9-32">wald_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;">summary</span>(alt_model)<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;">"B"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pr(&gt;|z|)"</span>]</span>
<span id="cb9-33"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wald test p-value (glm):"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(wald_p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Burden score U(0)      : 109.4711 
Var[U(0)]              : 22029.38 
Burden score statistic : 0.544 
Burden score p-value   : 0.4608 

Wald test p-value (glm): 0.4362 </code></pre>
</div>
</div>
<p>Two things stand out. First, the score and Wald p-values are close (0.46 and 0.44 land in the same non-significant territory), exactly the asymptotic equivalence discussed above. Second, and more importantly: <strong>the burden test completely misses this gene</strong>, despite it having six genuinely causal variants.</p>
<p>That’s not a bug in the implementation. It’s the burden test doing exactly what it’s designed to do, in a setting it’s poorly suited for.</p>
</section>
<section id="when-burden-tests-fail-the-variance-component-alternative" class="level1" data-number="9">
<h1 data-number="9"><span class="header-section-number">9</span> When Burden Tests Fail: The Variance-Component Alternative</h1>
<blockquote class="blockquote">
<p><strong>Why did the burden test fail here, specifically?</strong> Because four risk-increasing and two protective variants partially cancel out inside the same weighted sum. A burden test is only well-powered when all causal variants push risk in the same direction.</p>
</blockquote>
<p>The naive fix — summing single-variant score statistics <img src="https://latex.codecogs.com/png.latex?S_j%20=%20%5Csum_i%20g_%7Bi,j%7D(y_i%20-%20%5Chat%5Cpi_i)"> before squaring — has exactly this flaw:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AQ_B%20=%20%5Cleft(%5Csum_j%20w_j%20S_j%5Cright)%5E2%0A"></p>
<p>If variant A contributes <img src="https://latex.codecogs.com/png.latex?S_A%20=%20+5"> and variant B contributes <img src="https://latex.codecogs.com/png.latex?S_B%20=%20-5">, they cancel to zero and the association vanishes entirely, even though both variants are genuinely causal.</p>
<p>The fix, due to Wu et al.&nbsp;(2011) building on the C-alpha test of Neale et al.&nbsp;(2011), is to square each variant’s contribution <em>before</em> summing:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AQ_S%20=%20%5Csum_j%20w_j%5E2%20S_j%5E2%20=%20%5Csum_j%20w_j%5E2%5Cleft%5B%5Csum_i%20g_%7Bi,j%7D(y_i-%5Chat%5Cpi_i)%5Cright%5D%5E2%0A"></p>
<p>This is the <strong>SKAT</strong> (sequence kernel association test) statistic. Because residuals are squared before aggregation, risk-increasing and protective variants both contribute positively — nothing cancels.</p>
</section>
<section id="implementing-skat-from-scratch" class="level1" data-number="10">
<h1 data-number="10"><span class="header-section-number">10</span> Implementing SKAT From Scratch</h1>
<p><img src="https://latex.codecogs.com/png.latex?Q_S"> is a quadratic form in the vector of per-variant score statistics, and under the null it follows a <strong>mixture of weighted <img src="https://latex.codecogs.com/png.latex?%5Cchi%5E2_1"> distributions</strong> rather than a single chi-squared distribution — one weight per eigenvalue of the statistic’s covariance kernel. We build that kernel directly, residualizing the genotype matrix on the covariates first, then get a p-value using the four-moment chi-squared approximation of Liu, Tang &amp; Zhang (2009).</p>
<div id="eb670c8a" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:30.920207Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:30.918198Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:32.118477Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:32.116546Z&quot;}}" data-execution_count="7">
<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">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;">readRDS</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sim_data.rds"</span>)</span>
<span id="cb11-2">G <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>G; X <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>X; 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; maf <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>maf</span>
<span id="cb11-3">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;">dbeta</span>(maf, <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;">25</span>)</span>
<span id="cb11-4"></span>
<span id="cb11-5"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Null model (same as for the burden test) ---</span></span>
<span id="cb11-6">null_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;">glm</span>(y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> X[, <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;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">binomial</span>())</span>
<span id="cb11-7">pi_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;">fitted</span>(null_model)</span>
<span id="cb11-8">resid  <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> pi_hat</span>
<span id="cb11-9">V <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pi_hat <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> pi_hat)</span>
<span id="cb11-10"></span>
<span id="cb11-11"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 1: per-variant score statistics S_j = sum_i G_ij * resid_i ---</span></span>
<span id="cb11-12">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;">as.vector</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(G) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> resid)</span>
<span id="cb11-13"></span>
<span id="cb11-14"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 2: SKAT statistic Q_S = sum_j w_j^2 * S_j^2 ---</span></span>
<span id="cb11-15">Q_skat <span class="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>(w<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> 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;">2</span>)</span>
<span id="cb11-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SKAT statistic Q_S:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(Q_skat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb11-17"></span>
<span id="cb11-18"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 3: null distribution of Q_S is a mixture of weighted chi-sq(1)'s.</span></span>
<span id="cb11-19"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Its "kernel" matrix comes from projecting G onto the space orthogonal to X</span></span>
<span id="cb11-20"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## (so covariates are properly accounted for), then reweighting by w and V.</span></span>
<span id="cb11-21">Gt <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> 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;">solve</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</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;">t</span>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> G)     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># residualize G on X</span></span>
<span id="cb11-22">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;">diag</span>(w)</span>
<span id="cb11-23">K  <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;">t</span>(Gt) <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;">diag</span>(V) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> Gt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> W               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># q x q kernel matrix</span></span>
<span id="cb11-24">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;">eigen</span>(K, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">symmetric =</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;">only.values =</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>values</span>
<span id="cb11-25">lambda <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lambda[lambda <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;">1e-8</span>]</span>
<span id="cb11-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Eigenvalues of the kernel matrix:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(lambda, <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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb11-27"></span>
<span id="cb11-28"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## --- Step 4: Liu, Tang &amp; Zhang (2009) moment-matching chi-square approximation ---</span></span>
<span id="cb11-29">liu_pvalue <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>(Q, lambda) {</span>
<span id="cb11-30">  c1 <span class="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>(lambda)</span>
<span id="cb11-31">  c2 <span class="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>(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;">2</span>)</span>
<span id="cb11-32">  c3 <span class="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>(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;">3</span>)</span>
<span id="cb11-33">  c4 <span class="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>(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;">4</span>)</span>
<span id="cb11-34">  s1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c3 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> c2<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;">1.5</span></span>
<span id="cb11-35">  s2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c4 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> c2<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="cb11-36"></span>
<span id="cb11-37">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (s1<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;">&gt;</span> s2) {</span>
<span id="cb11-38">    a     <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> (s1 <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>(s1<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> s2))</span>
<span id="cb11-39">    delta <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> s1 <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><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> a<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="cb11-40">    df    <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="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;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> delta</span>
<span id="cb11-41">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb11-42">    a     <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> s1</span>
<span id="cb11-43">    delta <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>
<span id="cb11-44">    df    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c2<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> c3<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="cb11-45">  }</span>
<span id="cb11-46">  muQ    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c1</span>
<span id="cb11-47">  sigmaQ <span class="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>(<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> c2)</span>
<span id="cb11-48">  muX    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> delta</span>
<span id="cb11-49">  sigmaX <span class="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>(<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> (df <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> delta))</span>
<span id="cb11-50"></span>
<span id="cb11-51">  Qnorm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (Q <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> muQ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> sigmaQ <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> sigmaX <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> muX</span>
<span id="cb11-52">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pchisq</span>(Qnorm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> df, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncp =</span> delta, <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-53">}</span>
<span id="cb11-54"></span>
<span id="cb11-55">p_skat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">liu_pvalue</span>(Q_skat, lambda)</span>
<span id="cb11-56"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SKAT p-value (Liu et al. 2009 approximation):"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p_skat, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>SKAT statistic Q_S: 45891.8 
Eigenvalues of the kernel matrix: 3155.72 2340.21 2230.61 1851.55 1809.8 1770.95 1683.92 1596.49 1357.32 865.01 511.66 502.97 
SKAT p-value (Liu et al. 2009 approximation): 0.01069 </code></pre>
</div>
</div>
<p>SKAT recovers the association (p = 0.011) that the burden test missed entirely (p = 0.46), on the exact same data. This is the textbook case for variance-component tests: causal variants with mixed effect directions.</p>
<p>It’s worth checking this analytic p-value against a direct simulation, since the moment-matching approximation is, after all, an approximation.</p>
<div id="b5ad44d4" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:32.123288Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:32.121615Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:38.417234Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:38.415171Z&quot;}}" data-execution_count="8">
<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">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;">readRDS</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sim_data.rds"</span>)</span>
<span id="cb13-2">G <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>G; X <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>X; 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; maf <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>maf</span>
<span id="cb13-3">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;">dbeta</span>(maf, <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;">25</span>)</span>
<span id="cb13-4"></span>
<span id="cb13-5">null_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;">glm</span>(y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> X[, <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;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">binomial</span>())</span>
<span id="cb13-6">pi_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;">fitted</span>(null_model)</span>
<span id="cb13-7">V <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pi_hat <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> pi_hat)</span>
<span id="cb13-8"></span>
<span id="cb13-9">Q_obs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> {</span>
<span id="cb13-10">  resid <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> pi_hat</span>
<span id="cb13-11">  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;">as.vector</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(G) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> resid)</span>
<span id="cb13-12">  <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><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> 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;">2</span>)</span>
<span id="cb13-13">}</span>
<span id="cb13-14"></span>
<span id="cb13-15"><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="cb13-16">B <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;">20000</span></span>
<span id="cb13-17">Q_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;">numeric</span>(B)</span>
<span id="cb13-18"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (b <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>(B)) {</span>
<span id="cb13-19">  y_perm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</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>(y), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, pi_hat)        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># simulate under the fitted null</span></span>
<span id="cb13-20">  resid_perm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> y_perm <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> pi_hat</span>
<span id="cb13-21">  S_perm <span class="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.vector</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(G) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> resid_perm)</span>
<span id="cb13-22">  Q_null[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;">sum</span>(w<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> S_perm<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="cb13-23">}</span>
<span id="cb13-24"></span>
<span id="cb13-25">p_mc <span class="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>(Q_null <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> Q_obs)</span>
<span id="cb13-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Monte Carlo p-value ("</span>, B, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null draws ):"</span>, p_mc, <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>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Monte Carlo p-value ( 20000 null draws ): 0.01505 </code></pre>
</div>
</div>
<p>0.015 against the analytic 0.011: close enough to trust the moment-matching approximation for this gene, and a good habit to keep whenever a new test statistic goes into a pipeline.</p>
</section>
<section id="skat-o-combining-burden-and-variance-component-information" class="level1" data-number="11">
<h1 data-number="11"><span class="header-section-number">11</span> SKAT-O: Combining Burden and Variance-Component Information</h1>
<p>Neither test is uniformly better. Burden tests are more powerful when every causal variant pushes the trait in the same direction; SKAT is more powerful when effects are mixed or only a subset of variants are causal. <strong>SKAT-O</strong> (Lee et al., 2012) sidesteps the choice by taking a weighted combination of both statistics:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AQ_%7B%5Ctext%7BSKAT-O%7D%7D%20=%20(1-%5Crho)Q_S%20+%20%5Crho%20Q_B,%20%5Cqquad%200%20%5Cle%20%5Crho%20%5Cle%201%0A"></p>
<p>and searching over a grid of <img src="https://latex.codecogs.com/png.latex?%5Crho"> values, with a correction for having tested several of them. <img src="https://latex.codecogs.com/png.latex?%5Crho=0"> recovers pure SKAT; <img src="https://latex.codecogs.com/png.latex?%5Crho=1"> recovers the pure burden test.</p>
<div id="f94c43bd" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:38.422082Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:38.420519Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:38.773796Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:38.771965Z&quot;}}" data-execution_count="9">
<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">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;">readRDS</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sim_data.rds"</span>)</span>
<span id="cb15-2">G <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>G; X <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>X; 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; maf <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>maf</span>
<span id="cb15-3">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;">dbeta</span>(maf, <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;">25</span>)</span>
<span id="cb15-4"></span>
<span id="cb15-5">null_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;">glm</span>(y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> X[, <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;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">binomial</span>())</span>
<span id="cb15-6">pi_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;">fitted</span>(null_model)</span>
<span id="cb15-7">resid  <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> pi_hat</span>
<span id="cb15-8">V <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pi_hat <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> pi_hat)</span>
<span id="cb15-9"></span>
<span id="cb15-10">B_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;">as.vector</span>(G <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> w)</span>
<span id="cb15-11">U0      <span class="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>(resid <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> B_score)</span>
<span id="cb15-12">var_U0  <span class="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>(V <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> B_score<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="cb15-13">Q_B     <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> U0<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> var_U0                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># burden statistic (as a chi-sq_1)</span></span>
<span id="cb15-14"></span>
<span id="cb15-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;">as.vector</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(G) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> resid)</span>
<span id="cb15-16">Q_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;">sum</span>(w<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> 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;">2</span>)                    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># SKAT statistic</span></span>
<span id="cb15-17"></span>
<span id="cb15-18">liu_pvalue <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>(Q, lambda) {</span>
<span id="cb15-19">  c1 <span class="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>(lambda); c2 <span class="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>(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;">2</span>); c3 <span class="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>(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;">3</span>); c4 <span class="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>(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;">4</span>)</span>
<span id="cb15-20">  s1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c3 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> c2<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;">1.5</span>; s2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c4 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> c2<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="cb15-21">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (s1<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;">&gt;</span> s2) {</span>
<span id="cb15-22">    a <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> (s1 <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>(s1<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> s2)); delta <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> s1 <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><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> a<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>; df <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="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;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> delta</span>
<span id="cb15-23">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb15-24">    a <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> s1; delta <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>; df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c2<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> c3<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="cb15-25">  }</span>
<span id="cb15-26">  muQ <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c1; sigmaQ <span class="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>(<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> c2); muX <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> delta; sigmaX <span class="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>(<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> (df <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> delta))</span>
<span id="cb15-27">  Qnorm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (Q <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> muQ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> sigmaQ <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> sigmaX <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> muX</span>
<span id="cb15-28">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pchisq</span>(Qnorm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> df, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncp =</span> delta, <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="cb15-29">}</span>
<span id="cb15-30"></span>
<span id="cb15-31">Gt <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> 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;">solve</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</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;">t</span>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> G)</span>
<span id="cb15-32">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;">diag</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;">t</span>(Gt) <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;">diag</span>(V) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> Gt <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;">diag</span>(w)</span>
<span id="cb15-33">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;">eigen</span>(K, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">symmetric =</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;">only.values =</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>values</span>
<span id="cb15-34">lambda <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lambda[lambda <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;">1e-8</span>]</span>
<span id="cb15-35"></span>
<span id="cb15-36">rhos <span class="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.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.4</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;">0.8</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;"># rho = 1 recovers the pure burden test</span></span>
<span id="cb15-37">p_by_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;">sapply</span>(rhos, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(rho) {</span>
<span id="cb15-38">  Q_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;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> rho) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> Q_S <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> rho <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> Q_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;">sum</span>(w<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;"># rescale so burden/SKAT are comparable</span></span>
<span id="cb15-39">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">liu_pvalue</span>(Q_rho, (<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> rho) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lambda <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> rho <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><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;">mean</span>(lambda) <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><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb15-40">})</span>
<span id="cb15-41"></span>
<span id="cb15-42"><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;">rho =</span> rhos, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_value =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p_by_rho, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb15-43"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Minimum p-value across rho grid:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(p_by_rho), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb15-44">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"at rho ="</span>, rhos[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.min</span>(p_by_rho)], <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>)</span>
<span id="cb15-45"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(SKAT-O then applies its own correction for testing multiple rho values;</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>,</span>
<span id="cb15-46">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" shown here to illustrate the interpolation, not as a calibrated final p-value.)</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>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 7 × 2</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">rho</th>
<th data-quarto-table-cell-role="th" scope="col">p_value</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0.0</td>
<td>0.01069</td>
</tr>
<tr class="even">
<td>0.1</td>
<td>0.01989</td>
</tr>
<tr class="odd">
<td>0.2</td>
<td>0.03765</td>
</tr>
<tr class="even">
<td>0.4</td>
<td>0.13442</td>
</tr>
<tr class="odd">
<td>0.6</td>
<td>0.41188</td>
</tr>
<tr class="even">
<td>0.8</td>
<td>0.84245</td>
</tr>
<tr class="odd">
<td>1.0</td>
<td>0.99938</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>
Minimum p-value across rho grid: 0.01069 at rho = 0 
(SKAT-O then applies its own correction for testing multiple rho values;
  shown here to illustrate the interpolation, not as a calibrated final p-value.)</code></pre>
</div>
</div>
<p>For this gene, <img src="https://latex.codecogs.com/png.latex?%5Crho%20=%200"> (pure SKAT) is best, which is exactly what we’d expect given the bidirectional effect design. Note that this implementation illustrates the interpolation qualitatively rather than reproducing Lee et al.’s exact null distribution, which accounts for the correlation between the burden and SKAT statistics across the whole <img src="https://latex.codecogs.com/png.latex?%5Crho"> grid through a more involved numerical integration.</p>
</section>
<section id="which-variants-go-into-the-test" class="level1" data-number="12">
<h1 data-number="12"><span class="header-section-number">12</span> Which Variants Go Into the Test?</h1>
<p>A gene-based test is only as good as the variant set fed into it. In practice, variants are grouped by predicted functional consequence before testing:</p>
<ul>
<li><strong>Loss-of-function (LoF)</strong>: nonsense, frameshift, splice-disrupting</li>
<li><strong>Damaging missense</strong>: amino-acid-changing variants predicted deleterious by tools like CADD, PolyPhen, or SIFT</li>
<li><strong>Synonymous</strong>: typically included as a negative control, since these shouldn’t affect protein function</li>
</ul>
<p>Different genes show enrichment for different variant classes depending on their biology, so most modern rare-variant pipelines run several MAF cutoffs (e.g., &lt;1%, &lt;0.1%, &lt;0.01%) crossed with several annotation categories for each gene, rather than committing to one variant set up front.</p>
</section>
<section id="the-hidden-problem-at-biobank-scale-case-control-imbalance" class="level1" data-number="13">
<h1 data-number="13"><span class="header-section-number">13</span> The Hidden Problem at Biobank Scale: Case-Control Imbalance</h1>
<p>Everything above relies on the Central Limit Theorem: the null distribution of a score statistic is assumed to converge to a symmetric Normal. That assumption quietly depends on having enough carriers <em>and</em> a reasonably balanced number of cases and controls. Biobank-scale binary traits routinely have neither.</p>
<p>We can see this directly by simulating the null distribution of a single-variant score statistic under three regimes.</p>
<div id="0d081324" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:38.778707Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:38.777205Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:13:59.803315Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:13:59.801508Z&quot;}}" data-execution_count="10">
<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"><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="cb17-2">n <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;">5000</span></span>
<span id="cb17-3"></span>
<span id="cb17-4">simulate_null_scores <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>(maf, case_rate, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">B =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50000</span>) {</span>
<span id="cb17-5">  pi_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;">rep</span>(case_rate, n)               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># null model: no covariates, intercept only</span></span>
<span id="cb17-6">  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;">rbinom</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, maf)</span>
<span id="cb17-7">  V <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pi_hat <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> pi_hat)</span>
<span id="cb17-8">  var_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;">sum</span>(V <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><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb17-9">  sd_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>(var_S)</span>
<span id="cb17-10"></span>
<span id="cb17-11">  scores <span class="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>(B, {</span>
<span id="cb17-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;">rbinom</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, pi_hat)</span>
<span id="cb17-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(g <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> pi_hat))</span>
<span id="cb17-14">  })</span>
<span id="cb17-15">  <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;">scores =</span> scores <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> sd_S, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">g =</span> g)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># standardized score statistic</span></span>
<span id="cb17-16">}</span>
<span id="cb17-17"></span>
<span id="cb17-18">common_balanced <span class="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_null_scores</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">maf =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.30</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">case_rate =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.50</span>)</span>
<span id="cb17-19">rare_balanced   <span class="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_null_scores</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">maf =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.005</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">case_rate =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.50</span>)</span>
<span id="cb17-20">rare_imbalanced <span class="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_null_scores</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">maf =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.005</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">case_rate =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.01</span>)</span>
<span id="cb17-21"></span>
<span id="cb17-22">report <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>(label, scores) {</span>
<span id="cb17-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</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;">"%-28s skewness = %6.3f   empirical tail P(Z&gt;3) = %.5f (Normal approx: %.5f)</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>,</span>
<span id="cb17-24">              label, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(((scores <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>(scores)) <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;">sd</span>(scores))<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="cb17-25">              <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(scores <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;">3</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pnorm</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;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)))</span>
<span id="cb17-26">}</span>
<span id="cb17-27"></span>
<span id="cb17-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">report</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Common variant, balanced"</span>,   common_balanced<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scores)</span>
<span id="cb17-29"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">report</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Rare variant, balanced"</span>,     rare_balanced<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scores)</span>
<span id="cb17-30"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">report</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Rare variant, imbalanced"</span>,   rare_imbalanced<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scores)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Common variant, balanced     skewness =  0.006   empirical tail P(Z&gt;3) = 0.00120 (Normal approx: 0.00135)
Rare variant, balanced       skewness = -0.018   empirical tail P(Z&gt;3) = 0.00090 (Normal approx: 0.00135)
Rare variant, imbalanced     skewness =  1.292   empirical tail P(Z&gt;3) = 0.02412 (Normal approx: 0.00135)</code></pre>
</div>
</div>
<p>The common-variant and rare-but-balanced cases match the Normal approximation closely, exactly as CLT theory promises. The rare-and-imbalanced case is a different story: skewness jumps to 1.29, and the true tail probability is nearly 18-fold larger than the Normal approximation would suggest.</p>
<p>That’s not a small correction. At genome-wide or exome-wide significance thresholds (typically <img src="https://latex.codecogs.com/png.latex?5%5Ctimes10%5E%7B-8%7D"> or stricter after multiple testing correction), an 18-fold underestimate of the p-value in the tail translates directly into false positives.</p>
</section>
<section id="the-saddlepoint-approximation-fixing-the-tail" class="level1" data-number="14">
<h1 data-number="14"><span class="header-section-number">14</span> The Saddlepoint Approximation: Fixing the Tail</h1>
<blockquote class="blockquote">
<p><strong>If the Normal approximation only uses the mean and variance, what would a better approximation use?</strong> Every moment of the distribution, via its cumulant generating function (CGF), and — critically — it approximates the distribution <em>at the specific point in the tail you care about</em>, rather than at the center.</p>
</blockquote>
<p>The CGF is the log of the moment generating function, <img src="https://latex.codecogs.com/png.latex?K(t)%20=%20%5Clog%20%5Cmathbb%7BE%7D%5Be%5E%7BtX%7D%5D">. Its derivatives at <img src="https://latex.codecogs.com/png.latex?t=0"> recover the ordinary moments (variance, skewness, kurtosis), but its real advantage is computational: because our score statistic is a sum of independent per-individual contributions, <img src="https://latex.codecogs.com/png.latex?K(t)"> for the total is just the <strong>sum</strong> of each individual’s CGF, whereas the moment generating functions would need to be <strong>multiplied</strong> — a much less numerically stable operation once you’re summing thousands of terms.</p>
<p>The saddlepoint approximation (SPA) uses the full CGF to re-center the approximation exactly at the observed test statistic, rather than at the mean. It solves for a ‘tilting’ parameter <img src="https://latex.codecogs.com/png.latex?%5Chat%20t"> satisfying <img src="https://latex.codecogs.com/png.latex?K'(%5Chat%20t)%20=%20q_%7B%5Ctext%7Bobs%7D%7D">, then uses the curvature of <img src="https://latex.codecogs.com/png.latex?K"> at that point to get an accurate tail probability — the Lugannani-Rice formula. This is the method behind SAIGE-GENE+’s improved type-I error control at rare, imbalanced traits.</p>
<div id="5e706971" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:13:59.809252Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:13:59.807685Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:18:05.072494Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:18:05.070712Z&quot;}}" data-execution_count="11">
<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"><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="cb19-2">n <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;">5000</span></span>
<span id="cb19-3">maf <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.005</span></span>
<span id="cb19-4">case_rate <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.01</span></span>
<span id="cb19-5">pi_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;">rep</span>(case_rate, n)</span>
<span id="cb19-6">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;">rbinom</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, maf)</span>
<span id="cb19-7"></span>
<span id="cb19-8">sigma <span class="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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(pi_hat <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> pi_hat) <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><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb19-9"></span>
<span id="cb19-10"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## CGF of a single term X_i = g_i * (Y_i - pi_i), Y_i ~ Bernoulli(pi_i)</span></span>
<span id="cb19-11">K_i  <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>(t, g_i, p_i) <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="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> p_i) <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>t <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> g_i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> p_i) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> p_i <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>(t <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> g_i <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> p_i)))</span>
<span id="cb19-12">K1_i <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>(t, g_i, p_i) { h <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;">1e-5</span>; (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">K_i</span>(t <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> h, g_i, p_i) <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;">K_i</span>(t <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> h, g_i, p_i)) <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> h) }</span>
<span id="cb19-13">K2_i <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>(t, g_i, p_i) { h <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;">1e-4</span>; (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">K_i</span>(t <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> h, g_i, p_i) <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;">K_i</span>(t, g_i, p_i) <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;">K_i</span>(t <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> h, g_i, p_i)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> h<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="cb19-14"></span>
<span id="cb19-15">K_total  <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>(t) <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;">sapply</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;">K_i</span>(t, g[i], pi_hat[i])))</span>
<span id="cb19-16">K1_total <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>(t) <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;">sapply</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;">K1_i</span>(t, g[i], pi_hat[i])))</span>
<span id="cb19-17">K2_total <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>(t) <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;">sapply</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;">K2_i</span>(t, g[i], pi_hat[i])))</span>
<span id="cb19-18"></span>
<span id="cb19-19"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Test statistic set at 3 standard deviations - the "borderline significant" region</span></span>
<span id="cb19-20">q_obs <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> sigma</span>
<span id="cb19-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigma ="</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(sigma, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" q_obs (3 sd) ="</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(q_obs, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb19-22"></span>
<span id="cb19-23"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Solve the saddlepoint equation K'(t_hat) = q_obs</span></span>
<span id="cb19-24">that <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <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>(t) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">K1_total</span>(t) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> q_obs, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">interval =</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;">1e-6</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>root</span>
<span id="cb19-25"></span>
<span id="cb19-26"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Lugannani-Rice saddlepoint approximation for P(S &gt;= q_obs)</span></span>
<span id="cb19-27">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;">sign</span>(that) <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>(<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> (that <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> q_obs <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;">K_total</span>(that)))</span>
<span id="cb19-28">u <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> that <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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">K2_total</span>(that))</span>
<span id="cb19-29">p_spa <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pnorm</span>(w, <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;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dnorm</span>(w) <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> u <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> w)</span>
<span id="cb19-30"></span>
<span id="cb19-31"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Compare to the naive Normal approximation using only mean &amp; variance</span></span>
<span id="cb19-32">p_normal <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pnorm</span>(q_obs, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</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;">sd =</span> sigma, <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="cb19-33"></span>
<span id="cb19-34"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Monte Carlo "ground truth"</span></span>
<span id="cb19-35">B <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;">2000000</span></span>
<span id="cb19-36">mc_scores <span class="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>(B, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(g <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;">rbinom</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, pi_hat) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> pi_hat)))</span>
<span id="cb19-37">p_mc <span class="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>(mc_scores <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> q_obs)</span>
<span id="cb19-38"></span>
<span id="cb19-39"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Saddlepoint t_hat        :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(that, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb19-40"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SPA p-value              :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p_spa, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb19-41"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Normal-approx p-value    :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p_normal, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb19-42"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Monte Carlo p-value      :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p_mc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"("</span>, B, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"draws )</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>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>sigma = 0.704  q_obs (3 sd) = 2.111 
Saddlepoint t_hat        : 1.6964 
SPA p-value              : 0.01289 
Normal-approx p-value    : 0.00135 
Monte Carlo p-value      : 0.01394 ( 2e+06 draws )</code></pre>
</div>
</div>
<p>The saddlepoint approximation (0.0129) tracks the 2-million-draw Monte Carlo truth (0.0139) closely. The Normal approximation (0.00135), by contrast, is off by roughly an order of magnitude at exactly the same test statistic. This single comparison is the entire justification for why SAIGE-GENE+, and every serious modern rare-variant tool, replaces the Normal approximation with SPA before reporting a p-value.</p>
</section>
<section id="choosing-a-method-in-practice" class="level1" data-number="15">
<h1 data-number="15"><span class="header-section-number">15</span> Choosing a Method in Practice</h1>
<p>No single test is correct for every study design. The right choice depends on relatedness structure, sample size, trait type, and case-control balance.</p>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Setting</th>
<th>Recommended approach</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Quantitative trait, unrelated samples, large N</td>
<td>SKAT, SMMAT, or EmmaX-SKAT</td>
</tr>
<tr class="even">
<td>Quantitative trait, related samples (any N)</td>
<td>SAIGE-GENE+, Regenie, or STAAR</td>
</tr>
<tr class="odd">
<td>Binary trait, balanced (case:control &gt; 1:10), unrelated</td>
<td>SKAT</td>
</tr>
<tr class="even">
<td>Binary trait, balanced, related samples</td>
<td>SMMAT, EmmaX-SKAT, or SAIGE-GENE+</td>
</tr>
<tr class="odd">
<td>Binary trait, imbalanced (case:control &lt; 1:10)</td>
<td>SAIGE-GENE+, Regenie, or STAAR (all use SPA)</td>
</tr>
</tbody>
</table>
<p>As a rule of thumb: the more imbalanced or related your samples, the more you need a method built around a mixed model with saddlepoint-corrected p-values, rather than a method that assumes independence and a Normal null.</p>
</section>
<section id="summary" class="level1" data-number="16">
<h1 data-number="16"><span class="header-section-number">16</span> Summary</h1>
<ol type="1">
<li>Rare variants are individually hard to detect, but collectively common enough to test as a group.</li>
<li>Burden tests and SKAT differ in one key assumption: whether causal effects within a gene point in the same direction.</li>
<li>Both are implemented as score tests specifically because biobank-scale analysis makes fitting the full alternative model, gene by gene, computationally infeasible.</li>
<li>SKAT-O interpolates between burden and SKAT rather than forcing a choice between them.</li>
<li>At rare variant frequencies and with case-control imbalance, the Normal approximation that score tests rely on breaks down badly — the saddlepoint approximation is what makes modern tools like SAIGE-GENE+ trustworthy at genome-wide significance thresholds.</li>
</ol>
</section>
<section id="references" class="level1" data-number="17">
<h1 data-number="17"><span class="header-section-number">17</span> References</h1>
<p><strong>Foundational methods</strong></p>
<ul>
<li>Li, B. &amp; Leal, S. M. (2008). Methods for detecting associations with rare variants for common diseases: application to analysis of sequence data. <em>American Journal of Human Genetics</em>, 83, 311–321.</li>
<li>Madsen, B. E. &amp; Browning, S. R. (2009). A groupwise association test for rare mutations using a weighted sum statistic. <em>PLoS Genetics</em>, 5, e1000384.</li>
<li>Price, A. L. et al.&nbsp;(2010). Pooled association tests for rare variants in exon-resequencing studies. <em>American Journal of Human Genetics</em>, 86, 832–838.</li>
<li>Neale, B. M. et al.&nbsp;(2011). Testing for an unusual distribution of rare variants. <em>PLoS Genetics</em>, 7, e1001322.</li>
<li>Wu, M. C. et al.&nbsp;(2011). Rare-variant association testing for sequencing data with the sequence kernel association test. <em>American Journal of Human Genetics</em>, 89, 82–93.</li>
<li>Lee, S., Wu, M. C. &amp; Lin, X. (2012). Optimal tests for rare variant effects in sequencing association studies. <em>Biostatistics</em>, 13, 762–775.</li>
<li>Lee, S. et al.&nbsp;(2012). Optimal unified approach for rare-variant association testing with application to small-sample case-control whole-exome sequencing studies. <em>American Journal of Human Genetics</em>, 91, 224–237.</li>
<li>Liu, H., Tang, Y. &amp; Zhang, H. H. (2009). A new chi-square approximation to the distribution of non-negative definite quadratic forms in non-central normal variables. <em>Computational Statistics &amp; Data Analysis</em>, 53, 853–856.</li>
</ul>
<p><strong>Scalable software and applications</strong></p>
<ul>
<li>Zhou, W. et al.&nbsp;(2020). Scalable generalized linear mixed model for region-based association tests in large biobanks and cohorts. <em>Nature Genetics</em>, 52, 634–639.</li>
<li>Zhou, W., Bi, W., Zhao, Z. et al.&nbsp;(2022). SAIGE-GENE+ improves the efficiency and accuracy of set-based rare variant association tests. <em>Nature Genetics</em>, 54, 1466–1469.</li>
<li>Backman, J. D. et al.&nbsp;(2021). Exome sequencing and analysis of 454,787 UK Biobank participants. <em>Nature</em>, 599, 628–634.</li>
<li>Karczewski, K. J. et al.&nbsp;(2022). Systematic single-variant and gene-based association testing of thousands of phenotypes in 394,841 UK Biobank exomes. <em>Cell Genomics</em>, 2, 100168.</li>
</ul>


</section>

 ]]></description>
  <category>Statistical Genetics</category>
  <category>Rare Variants</category>
  <category>SKAT</category>
  <category>R</category>
  <guid>https://bntechie.github.io/tutorials/rare_variants/rare_variant_tutorial.html</guid>
  <pubDate>Fri, 19 Jun 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/rare_variants/images/rare-variant-tests.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Statistical Fine-Mapping: From GWAS Signals to Causal Variants</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/Finemapping/Statistical_Fine_Mapping.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/Finemapping/images/fine-mapping.svg" alt="Two panels comparing ABF and SuSiE fine-mapping on the same simulated GWAS region: ABF finds only 1 of 3 true causal SNPs, SuSiE finds all 3" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The result this tutorial builds up to, from real simulated data: with three true causal variants hiding in one correlated region, ABF collapses onto a single dominant signal while SuSiE separates out all three.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">Fine-Mapping</span> <span class="tag">SuSiE</span> <span class="tag">GWAS</span> <span class="tag">R</span></p>
</div>
<section id="what-is-fine-mapping" class="level2" data-number="0.1">
<h2 data-number="0.1" class="anchored" data-anchor-id="what-is-fine-mapping"><span class="header-section-number">0.1</span> What Is Fine-Mapping?</h2>
<p>GWAS has identified thousands of genomic regions associated with disease, but it typically doesn’t pinpoint the <em>causal</em> variant. Instead, GWAS flags a region containing many correlated variants, because of <strong>Linkage Disequilibrium (LD)</strong> — the non-random correlation between nearby genetic variants:</p>
<pre><code>SNP A ---- SNP B ---- SNP C
              ^
           causal</code></pre>
<p>If SNP B is causal, A and C often look significant too, simply because they’re inherited together.</p>
<blockquote class="blockquote">
<p><strong>GWAS asks:</strong> Which region is associated with the trait? <strong>Fine-mapping asks:</strong> Which specific variant is most likely causing it?</p>
</blockquote>
<p>A locus flagged by GWAS might contain 10, 100, or 1,000 SNPs with nearly identical p-values — GWAS alone cannot separate them.</p>
</section>
<section id="the-goal-posterior-inclusion-probabilities" class="level2" data-number="0.2">
<h2 data-number="0.2" class="anchored" data-anchor-id="the-goal-posterior-inclusion-probabilities"><span class="header-section-number">0.2</span> The Goal: Posterior Inclusion Probabilities</h2>
<p>Fine-mapping estimates <img src="https://latex.codecogs.com/png.latex?P(%5Ctext%7BSNP%20is%20causal%7D%20%5Cmid%20%5Ctext%7Bdata%7D)"> for every variant in a region — a <strong>Posterior Inclusion Probability (PIP)</strong> — rather than just a p-value.</p>
<div id="44699ac8" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:45.958879Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:45.950848Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:46.033032Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:46.028336Z&quot;}}" data-execution_count="1">
<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">results <span class="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;">SNP =</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;">"rs1"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs2"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs3"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs4"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs5"</span>),</span>
<span id="cb2-2">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">PIP =</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.04</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.88</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.02</span>))</span></code></pre></div></div>
</div>
<pre><code>rs1  0.01   rs2  0.04   rs3  0.88   rs4  0.05   rs5  0.02</code></pre>
<p>rs3, with an 88% posterior probability, is the strongest causal candidate.</p>
<table class="caption-top table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th></th>
<th>GWAS</th>
<th>Fine-mapping</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Focus</td>
<td>p-values, association testing, genome-wide discovery</td>
<td>posterior probabilities, causal inference, variant prioritization</td>
</tr>
<tr class="even">
<td>Role</td>
<td>first step</td>
<td>second step</td>
</tr>
</tbody>
</table>
</section>
<section id="why-it-matters" class="level2" data-number="0.3">
<h2 data-number="0.3" class="anchored" data-anchor-id="why-it-matters"><span class="header-section-number">0.3</span> Why It Matters</h2>
<p>A schizophrenia GWAS locus with 200 SNPs is too expensive to validate experimentally in full. Fine-mapping can shrink the candidate list to 3 variants, or even 1 — dramatically cutting the cost of functional genomics, drug target discovery, eQTL interpretation, colocalization, and precision medicine.</p>
</section>
<section id="the-modern-statistical-genetics-pipeline" class="level2" data-number="0.4">
<h2 data-number="0.4" class="anchored" data-anchor-id="the-modern-statistical-genetics-pipeline"><span class="header-section-number">0.4</span> The Modern Statistical Genetics Pipeline</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGenotypes%7D%20%5Crightarrow%20%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BSignificant%20Locus%7D%20%5Crightarrow%20%5Ctext%7BLD%20Matrix%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BPIPs%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Analysis%7D%20%5Crightarrow%20%5Ctext%7BColocalization%7D%20%5Crightarrow%20%5Ctext%7BCandidate%20Gene%7D"></p>
<p>This backbone underlies large-scale projects like UK Biobank, FinnGen, the Psychiatric Genomics Consortium, and GTEx.</p>
</section>
<section id="what-data-do-you-need" class="level2" data-number="0.5">
<h2 data-number="0.5" class="anchored" data-anchor-id="what-data-do-you-need"><span class="header-section-number">0.5</span> What Data Do You Need?</h2>
<p>Three common scenarios determine what’s possible:</p>
<ol type="1">
<li><strong>Individual-level data</strong> — genotypes and phenotypes for every participant. Ideal: LD can be computed directly from the sample.</li>
<li><strong>Single-cohort GWAS summary statistics</strong> — only beta, SE, p-value. Requires an external LD reference panel (1000 Genomes, UK Biobank, TOPMed).</li>
<li><strong>Meta-analysis summary statistics</strong> — combined across cohorts with different LD structures; the hardest case, often requiring specialized methods (FastMap, CARMA, SLALOM).</li>
</ol>
</section>
<section id="the-central-role-of-ld" class="level2" data-number="0.6">
<h2 data-number="0.6" class="anchored" data-anchor-id="the-central-role-of-ld"><span class="header-section-number">0.6</span> The Central Role of LD</h2>
<p>Two SNPs with <img src="https://latex.codecogs.com/png.latex?r%5E2%20=%200.95"> are almost perfectly correlated — statistically indistinguishable. High LD → large credible sets, low resolution. Low LD → small credible sets, high resolution. This is why ancestry-matched LD reference panels matter so much.</p>
<p><strong>Foundational concepts for the rest of this tutorial:</strong> Linkage Disequilibrium, Causal Variants, Posterior Inclusion Probability, Credible Sets, LD Reference Panels, Summary Statistics, Individual-Level Data.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Fine-mapping identifies likely causal variants within a GWAS locus. Because neighboring SNPs are correlated through LD, GWAS alone can’t determine which variant is responsible. Fine-mapping combines GWAS statistics with LD and Bayesian inference to assign causality probabilities, producing PIPs and credible sets — the bridge between GWAS discovery and downstream eQTL mapping, colocalization, functional validation, and drug target identification.</p>
</blockquote>
</section>
<section id="linkage-disequilibrium-pips-and-credible-sets" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Linkage Disequilibrium, PIPs, and Credible Sets</h1>
<p>Three concepts form the mathematical backbone of every fine-mapping method: <strong>Linkage Disequilibrium (LD)</strong>, <strong>Posterior Inclusion Probabilities (PIPs)</strong>, and <strong>Credible Sets</strong>.</p>
<section id="linkage-disequilibrium" class="level2" data-number="1.1">
<h2 data-number="1.1" class="anchored" data-anchor-id="linkage-disequilibrium"><span class="header-section-number">1.1</span> Linkage Disequilibrium</h2>
<p>LD measures the correlation between genetic variants — when two SNPs are inherited together more often than chance predicts, they’re in LD. If <img src="https://latex.codecogs.com/png.latex?r%5E2(%5Ctext%7BSNP1%7D,%20%5Ctext%7BSNP2%7D)%20=%200.95">, knowing one variant almost perfectly predicts the other.</p>
<p><strong>Why LD exists:</strong> during recombination, nearby variants are less likely to be separated, so physical proximity → co-inheritance → correlation → LD. The closer two SNPs sit, the stronger their LD tends to be.</p>
<p><strong>Two common measures:</strong> <img src="https://latex.codecogs.com/png.latex?D'"> (0–1, measures historical recombination) and <img src="https://latex.codecogs.com/png.latex?r%5E2"> (0–1, measures correlation; <img src="https://latex.codecogs.com/png.latex?r%5E2=0"> means no correlation, <img src="https://latex.codecogs.com/png.latex?r%5E2=1"> means perfect correlation). Fine-mapping primarily uses <img src="https://latex.codecogs.com/png.latex?r%5E2">.</p>
<p>Example 4×4 LD matrix, where SNP1–SNP2 and SNP3–SNP4 form two separate, tightly-correlated blocks:</p>
<div id="43d9178e" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:46.129471Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:46.042048Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:46.159820Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:46.153312Z&quot;}}" data-execution_count="2">
<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">ld <span class="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="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;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.00</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.92</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>),</span>
<span id="cb4-3">  <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.92</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.00</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.18</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.07</span>),</span>
<span id="cb4-4">  <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.15</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.18</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.00</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.85</span>),</span>
<span id="cb4-5">  <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.05</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.07</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.85</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.00</span>)</span>
<span id="cb4-6">))</span></code></pre></div></div>
</div>
</section>
<section id="posterior-inclusion-probability-pip" class="level2" data-number="1.2">
<h2 data-number="1.2" class="anchored" data-anchor-id="posterior-inclusion-probability-pip"><span class="header-section-number">1.2</span> Posterior Inclusion Probability (PIP)</h2>
<div id="b5d91117" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:46.172529Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:46.167692Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:46.199000Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:46.194739Z&quot;}}" data-execution_count="3">
<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">pip <span class="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;">SNP =</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;">"rs1"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs2"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs3"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs4"</span>),</span>
<span id="cb5-2">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">PIP =</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.03</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.07</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.82</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.08</span>))</span></code></pre></div></div>
</div>
<p>rs3 has an 82% probability of being causal.</p>
<p><strong>PIPs are not p-values.</strong> A p-value measures evidence against the null hypothesis; a PIP measures probability of causality. <img src="https://latex.codecogs.com/png.latex?p%20=%201%5Ctimes10%5E%7B-20%7D"> does <strong>not</strong> mean “99.999999999999999% chance causal” — that’s a common and incorrect conflation.</p>
<p><strong>Multiple causal variants are common.</strong> Many loci contain more than one causal SNP (e.g., variants 20, 39, and 68 all influencing the same trait) — exactly the scenario that motivated methods like SuSiE.</p>
</section>
<section id="credible-sets" class="level2" data-number="1.3">
<h2 data-number="1.3" class="anchored" data-anchor-id="credible-sets"><span class="header-section-number">1.3</span> Credible Sets</h2>
<p>A <strong>credible set</strong> is a group of variants that collectively contain the causal SNP with high probability — most commonly a <strong>95% credible set</strong>: a 95% probability the causal SNP lies <em>somewhere in the set</em>, not a 95% probability for each individual member.</p>
<p><strong>Constructing one:</strong> sort by PIP, then accumulate until crossing the threshold.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>SNP</th>
<th>PIP</th>
<th>Cumulative</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>rs1</td>
<td>0.60</td>
<td>0.60</td>
</tr>
<tr class="even">
<td>rs2</td>
<td>0.25</td>
<td>0.85</td>
</tr>
<tr class="odd">
<td>rs3</td>
<td>0.08</td>
<td>0.93</td>
</tr>
<tr class="even">
<td>rs4</td>
<td>0.04</td>
<td>0.97</td>
</tr>
<tr class="odd">
<td>rs5</td>
<td>0.03</td>
<td>1.00</td>
</tr>
</tbody>
</table>
<p>The 95% credible set is {rs1, rs2, rs3, rs4} — the smallest prefix exceeding 95%.</p>
<p><strong>Interpreting size:</strong> a single-SNP set (e.g.&nbsp;{rs25}) means excellent resolution; a 3-SNP set is reasonable; a 50-SNP set means poor resolution.</p>
</section>
<section id="what-determines-credible-set-size" class="level2" data-number="1.4">
<h2 data-number="1.4" class="anchored" data-anchor-id="what-determines-credible-set-size"><span class="header-section-number">1.4</span> What Determines Credible Set Size?</h2>
<ul>
<li><strong>Sample size</strong> — larger N → higher power → smaller credible sets.</li>
<li><strong>LD structure</strong> — high LD → large credible sets (SNPs statistically indistinguishable); low LD → small credible sets.</li>
<li><strong>Effect size</strong> — larger effects → higher PIPs; smaller effects → lower PIPs.</li>
</ul>
<p><strong>Ideal:</strong> one SNP at PIP = 0.98, credible set = {that SNP}. <strong>Difficult:</strong> five SNPs each around PIP 0.16–0.20, credible set = all five, reflecting genuine uncertainty rather than method failure.</p>
</section>
<section id="why-fine-mapping-is-bayesian" class="level2" data-number="1.5">
<h2 data-number="1.5" class="anchored" data-anchor-id="why-fine-mapping-is-bayesian"><span class="header-section-number">1.5</span> Why Fine-Mapping Is Bayesian</h2>
<p>Bayesian methods directly answer “how likely is each SNP to be causal?” — exactly the question fine-mapping needs. This is why nearly every modern method (ABF, SuSiE, FINEMAP, CARMA, CAVIAR) is Bayesian.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> LD is the correlation structure among nearby variants and the primary reason GWAS can’t identify causal variants directly. Fine-mapping combines LD with GWAS statistics to estimate PIPs. Because uncertainty remains, methods report credible sets — groups of variants that jointly contain the causal SNP with high probability. Sample size, effect size, and LD structure strongly influence both PIPs and credible set size.</p>
</blockquote>
</section>
</section>
<section id="bayesian-fine-mapping-and-approximate-bayes-factors-abf" class="level1" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Bayesian Fine-Mapping and Approximate Bayes Factors (ABF)</h1>
<p>GWAS cannot tell us which of several significant SNPs is causal — it only tells us how unlikely the data would be under no association. Fine-mapping needs something different: <img src="https://latex.codecogs.com/png.latex?P(%5Ctext%7Bcausal%7D%20%5Cmid%20%5Ctext%7Bdata%7D)">. This is where Bayesian statistics comes in, and <strong>Approximate Bayes Factors (ABF)</strong> — Jon Wakefield’s method — is one of the earliest and still most widely used solutions.</p>
<section id="frequentist-vs.-bayesian-thinking" class="level2" data-number="2.1">
<h2 data-number="2.1" class="anchored" data-anchor-id="frequentist-vs.-bayesian-thinking"><span class="header-section-number">2.1</span> Frequentist vs.&nbsp;Bayesian Thinking</h2>
<p>The frequentist approach tests <img src="https://latex.codecogs.com/png.latex?H_0:%20%5Cbeta%20=%200"> and computes <img src="https://latex.codecogs.com/png.latex?P(%5Ctext%7Bdata%7D%20%5Cmid%20%5Ctext%7Bnull%7D)"> — a p-value. The Bayesian approach compares “SNP is causal” against “SNP is not causal” and computes <img src="https://latex.codecogs.com/png.latex?P(%5Ctext%7Bcausal%7D%20%5Cmid%20%5Ctext%7Bdata%7D)"> directly — exactly the quantity we want.</p>
</section>
<section id="bayes-factors" class="level2" data-number="2.2">
<h2 data-number="2.2" class="anchored" data-anchor-id="bayes-factors"><span class="header-section-number">2.2</span> Bayes Factors</h2>
<p>A <strong>Bayes Factor</strong> compares two models: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BBF%7D%20=%20P(%5Ctext%7Bdata%7D%20%5Cmid%20%5Ctext%7Bcausal%7D)%20/%20P(%5Ctext%7Bdata%7D%20%5Cmid%20%5Ctext%7Bnull%7D)">. BF = 1 means no preference; BF = 10 means the data are 10× more likely under the causal model; BF = 100 is strong evidence for causality.</p>
<p><strong>“Approximate”</strong> because exact Bayes Factors are expensive to compute. Wakefield’s approximation needs only the effect estimate (<img src="https://latex.codecogs.com/png.latex?%5Cbeta">) and its standard error (SE) — both routinely available in GWAS summary statistics, with no individual-level data required.</p>
</section>
<section id="wakefields-abf-formula" class="level2" data-number="2.3">
<h2 data-number="2.3" class="anchored" data-anchor-id="wakefields-abf-formula"><span class="header-section-number">2.3</span> Wakefield’s ABF Formula</h2>
<p>For each SNP, compute <img src="https://latex.codecogs.com/png.latex?Z%20=%20%5Cbeta/%5Ctext%7BSE%7D"> and <img src="https://latex.codecogs.com/png.latex?V%20=%20%5Ctext%7BSE%7D%5E2">. Choose a prior variance <img src="https://latex.codecogs.com/png.latex?W"> (commonly 0.01–0.04, representing your prior belief about plausible effect sizes — smaller <img src="https://latex.codecogs.com/png.latex?W"> expects smaller effects). Then:</p>
<p><img src="https://latex.codecogs.com/png.latex?r%20=%20%5Cfrac%7BW%7D%7BW+V%7D,%20%5Cqquad%20%5Clog%5Ctext%7BBF%7D%20=%20%5Cfrac%7B%5Clog(1-r)%20+%20rZ%5E2%7D%7B2%7D"></p>
</section>
<section id="from-bayes-factors-to-pips" class="level2" data-number="2.4">
<h2 data-number="2.4" class="anchored" data-anchor-id="from-bayes-factors-to-pips"><span class="header-section-number">2.4</span> From Bayes Factors to PIPs</h2>
<p>Normalize the BFs across all SNPs in the region: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPIP%7D_i%20=%20%5Ctext%7BBF%7D_i%20/%20%5Csum_j%20%5Ctext%7BBF%7D_j">.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><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, pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb6-2"></span>
<span id="cb6-3">beta <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([<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.15</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.09</span>])</span>
<span id="cb6-4">se   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.03</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.03</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.03</span>])</span>
<span id="cb6-5">W <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.04</span></span>
<span id="cb6-6"></span>
<span id="cb6-7">z <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> beta <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> se</span>
<span id="cb6-8">V <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> se<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>
<span id="cb6-9">r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> W <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (W <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> V)</span>
<span id="cb6-10">lbf <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;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>r) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(z<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> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb6-11">bf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.exp(lbf)</span>
<span id="cb6-12">pip <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> bf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> bf.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span>
<span id="cb6-13"></span>
<span id="cb6-14">results <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;">"Beta"</span>: beta, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SE"</span>: se, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Z"</span>: z, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BF"</span>: bf, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PIP"</span>: pip})</span></code></pre></div></div>
<p>For example, three SNPs with BFs 3, 50, and 10 (total 63) give PIPs of 0.048, 0.794, and 0.159 — SNP2 is the strongest candidate.</p>
</section>
<section id="the-single-causal-variant-assumption" class="level2" data-number="2.5">
<h2 data-number="2.5" class="anchored" data-anchor-id="the-single-causal-variant-assumption"><span class="header-section-number">2.5</span> The Single-Causal-Variant Assumption</h2>
<p>ABF assumes exactly <strong>one causal variant per locus</strong> — a simplification that breaks down whenever a locus actually has 2, 3, 5, or more independent causal signals (variants 20, 39, and 68, say). ABF then splits and dilutes the true signals across correlated SNPs, since it can only ever “explain” the locus with one variant. This limitation directly motivated SuSiE, FINEMAP, CAVIAR, and CARMA.</p>
</section>
<section id="strengths-and-limitations" class="level2" data-number="2.6">
<h2 data-number="2.6" class="anchored" data-anchor-id="strengths-and-limitations"><span class="header-section-number">2.6</span> Strengths and Limitations</h2>
<p><strong>Strengths:</strong> fast, simple, requires only summary statistics, no LD matrix needed, computationally efficient for large GWAS. <strong>Limitations:</strong> single-causal-variant assumption, cannot separate multiple signals, can be confused by strong LD, lower resolution in complex regions.</p>
<p>ABF also underlies <code>coloc.abf</code>, used for testing whether GWAS and eQTL signals share a causal variant (Part 12) — carrying the same single-variant assumption into colocalization.</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%20Summary%20Statistics%7D%20%5Crightarrow%20Z%20%5Crightarrow%20%5Ctext%7BABF%7D%20%5Crightarrow%20%5Ctext%7BBayes%20Factors%7D%20%5Crightarrow%20%5Ctext%7BNormalize%7D%20%5Crightarrow%20%5Ctext%7BPIPs%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D"></p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> ABF was among the first practical Bayesian fine-mapping methods, converting GWAS summary statistics into PIPs by normalizing Bayes Factors across SNPs. It’s fast and requires only summary statistics, but its core limitation — assuming a single causal variant per locus — motivated the development of multi-signal methods like SuSiE.</p>
</blockquote>
</section>
</section>
<section id="susie-sum-of-single-effects" class="level1" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> SuSiE: Sum of Single Effects</h1>
<p>ABF assumes one causal variant per locus, but real GWAS regions routinely contain 2, 3, 5+ independent causal variants. <strong>SuSiE</strong> — one of the most widely used fine-mapping methods today — was built to handle exactly this.</p>
<section id="the-core-idea" class="level2" data-number="3.1">
<h2 data-number="3.1" class="anchored" data-anchor-id="the-core-idea"><span class="header-section-number">3.1</span> The Core Idea</h2>
<p>Instead of fitting one signal, SuSiE models the phenotype as a <strong>sum of single effects</strong>:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPhenotype%7D%20=%20%5Ctext%7BEffect%7D_1%20+%20%5Ctext%7BEffect%7D_2%20+%20%5Ctext%7BEffect%7D_3%20+%20%5Cdots,%20%5Cqquad%20y%20=%20Xb%20+%20e"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?y"> is the phenotype, <img src="https://latex.codecogs.com/png.latex?X"> the genotype matrix, <img src="https://latex.codecogs.com/png.latex?b"> the SNP effects, and <img src="https://latex.codecogs.com/png.latex?e"> noise. Rather than fitting all SNP effects simultaneously, SuSiE decomposes the model into separate single-effect components — each one identifying one potential causal signal (e.g.&nbsp;Signal 1 → variant 39, Signal 2 → variant 20, Signal 3 → variant 68) — then combines them.</p>
<p>The key parameter <strong>L</strong> sets the maximum number of causal signals to search for (e.g.&nbsp;<code>L = 4</code> allows up to 4 independent signals).</p>
</section>
<section id="what-susie-produces" class="level2" data-number="3.2">
<h2 data-number="3.2" class="anchored" data-anchor-id="what-susie-produces"><span class="header-section-number">3.2</span> What SuSiE Produces</h2>
<p>For every SNP, a <strong>PIP</strong> (e.g.&nbsp;rs20 = 0.95, rs39 = 0.98, rs68 = 0.92 — all three likely causal, unlike a single p-value). And for each independent signal, a <strong>credible set</strong> — sometimes tight ({rs20} alone, excellent resolution), sometimes broader ({rs20, rs21, rs22}, meaning one of these is probably causal but the data can’t distinguish which).</p>
</section>
<section id="running-susie-in-r" class="level2" data-number="3.3">
<h2 data-number="3.3" class="anchored" data-anchor-id="running-susie-in-r"><span class="header-section-number">3.3</span> Running SuSiE in R</h2>
<p><em>Illustrative syntax – the objects below (<code>GWAS_df</code>, <code>N</code>, <code>in_sample_LD</code>, <code>y</code>) are built from scratch in the worked example later in this tutorial.</em></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" 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;">library</span>(susieR)</span>
<span id="cb7-2"></span>
<span id="cb7-3">susie_results <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">susie_rss</span>(</span>
<span id="cb7-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bhat =</span> GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>beta_marginal,</span>
<span id="cb7-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shat =</span> GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>se_marginal,</span>
<span id="cb7-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> N,</span>
<span id="cb7-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">R =</span> in_sample_LD,</span>
<span id="cb7-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var_y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(y),</span>
<span id="cb7-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">L =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,</span>
<span id="cb7-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">estimate_residual_variance =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb7-11">)</span></code></pre></div></div>
<p>Unlike ABF, SuSiE <strong>requires an LD matrix</strong> — it has to know which SNPs are correlated in order to separate distinct signals.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" 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;">susie_plot</span>(susie_results, <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;">"PIP"</span>)</span></code></pre></div></div>
</section>
<section id="when-susie-works-best" class="level2" data-number="3.4">
<h2 data-number="3.4" class="anchored" data-anchor-id="when-susie-works-best"><span class="header-section-number">3.4</span> When SuSiE Works Best</h2>
<p>Large sample size (more information), lower LD (better separation between causal variants), strong effects (higher PIPs), and an accurate, ancestry-matched LD matrix.</p>
<p><strong>Common beginner mistake:</strong> assuming the lead SNP (smallest p-value) is automatically the causal SNP. SuSiE often shows lead SNP ≠ causal SNP, because the association signal can be distributed across correlated variants.</p>
</section>
<section id="susie-vs.-abf" class="level2" data-number="3.5">
<h2 data-number="3.5" class="anchored" data-anchor-id="susie-vs.-abf"><span class="header-section-number">3.5</span> SuSiE vs.&nbsp;ABF</h2>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Feature</th>
<th>ABF</th>
<th>SuSiE</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Bayesian</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>Uses summary statistics</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr class="odd">
<td>Uses LD matrix</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>Multiple signals</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="odd">
<td>Credible sets</td>
<td>Limited</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>Modern standard</td>
<td>No</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p>SuSiE became popular for combining accurate PIPs, multiple-signal detection, credible sets, computational efficiency, summary-statistics compatibility, and natural integration with colocalization.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> SuSiE (Sum of Single Effects) is a Bayesian method that models several independent causal signals simultaneously, rather than assuming a single causal SNP. It needs GWAS summary statistics plus an LD matrix, and produces PIPs and credible sets per signal — now one of the most widely used fine-mapping methods because it handles the complexity of real genetic loci.</p>
</blockquote>
</section>
</section>
<section id="running-a-complete-fine-mapping-analysis-step-by-step" class="level1" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> Running a Complete Fine-Mapping Analysis Step-by-Step</h1>
<p>With the concepts and methods in hand, here’s a complete, self-contained workflow — simulate a locus with known causal variants, run GWAS, then compare ABF against SuSiE.</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSimulate%20Genotypes%7D%20%5Crightarrow%20%5Ctext%7BSimulate%20Phenotype%7D%20%5Crightarrow%20%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BABF%7D%20%5Crightarrow%20%5Ctext%7BSuSiE%7D%20%5Crightarrow%20%5Ctext%7BInterpret%20PIPs%20%5C&amp;%20Credible%20Sets%7D"></p>
<div id="5cfb5c9b" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:46.211056Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:46.206511Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:47.893724Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:47.891378Z&quot;}}" data-execution_count="4">
<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;">library</span>(MASS)     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># data simulation</span></span>
<span id="cb9-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(susieR)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># fine-mapping</span></span>
<span id="cb9-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># visualization</span></span></code></pre></div></div>
</div>
<p><strong>Simulate a genomic region of <code>p &lt;- 100</code> SNPs with moderate LD (off-diagonal 0.3, diagonal 1):</strong></p>
<div id="ce5cf556" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:47.899659Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:47.897603Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:47.916506Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:47.914561Z&quot;}}" data-execution_count="5">
<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">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;">100</span></span>
<span id="cb10-2">LD <span class="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="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;">nrow =</span> p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncol =</span> p)</span>
<span id="cb10-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diag</span>(LD) <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></code></pre></div></div>
</div>
<p><strong>Simulate genotypes for <code>N &lt;- 1000</code> individuals</strong> using the LD matrix as the covariance structure:</p>
<div id="131ad5e6" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:47.921169Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:47.919589Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:47.948124Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:47.946268Z&quot;}}" data-execution_count="6">
<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"><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="cb11-2">N <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="cb11-3">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;">mvrnorm</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> N, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</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>, p), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Sigma =</span> LD)</span>
<span id="cb11-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># dim(X) -&gt; 1000 x 100</span></span></code></pre></div></div>
</div>
<p><strong>Define <code>L &lt;- 3</code> true causal SNPs, chosen at random</strong> (e.g.&nbsp;variants 68, 39, 1 — the workshop’s exact setup):</p>
<div id="863fbfba" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:47.952580Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:47.950828Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:47.964328Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:47.962510Z&quot;}}" data-execution_count="7">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb12-2">L <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="cb12-3">causal_ind <span class="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="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, L, <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;">FALSE</span>)</span></code></pre></div></div>
</div>
<p><strong>Assign effect sizes for a target heritability, e.g.&nbsp;<code>h2g &lt;- 0.1</code>:</strong></p>
<div id="0085ce1f" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:47.968853Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:47.967037Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:47.984982Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:47.982888Z&quot;}}" data-execution_count="8">
<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">h2g <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="cb13-2">per_snp_h2g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> h2g <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> L</span>
<span id="cb13-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;">5</span>)</span>
<span id="cb13-4">effect_sizes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(L, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</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;">sd =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(per_snp_h2g))</span>
<span id="cb13-5"></span>
<span id="cb13-6">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;">rep</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, p)</span>
<span id="cb13-7">beta[causal_ind] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> effect_sizes</span>
<span id="cb13-8">genetic_effect <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> X <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> beta</span></code></pre></div></div>
</div>
<p><strong>Simulate the phenotype by adding environmental noise:</strong></p>
<div id="daa08136" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:47.988976Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:47.987919Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:48.002841Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:48.001039Z&quot;}}" data-execution_count="9">
<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">var_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;">var</span>(genetic_effect)</span>
<span id="cb14-2">sigma_squared <span class="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="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> var_g <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.05</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> var_g, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>)</span>
<span id="cb14-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;">105</span>)</span>
<span id="cb14-4">epsilon <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(N, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</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;">sd =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(sigma_squared))</span>
<span id="cb14-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;">as.numeric</span>(genetic_effect <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> epsilon)</span></code></pre></div></div>
</div>
<p><strong>Run GWAS</strong> — one univariate regression per SNP, producing a full summary-statistics table:</p>
<div id="467ebc29" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:48.008073Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:48.006475Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:48.141066Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:48.138637Z&quot;}}" data-execution_count="10">
<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">GWAS_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;">beta =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(p), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(p), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">z =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(p), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pval =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(p))</span>
<span id="cb15-2"></span>
<span id="cb15-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" 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="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>p) {</span>
<span id="cb15-4">  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;">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> X[,i] <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="cb15-5">  beta_hat <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>coefficients[<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;">"Estimate"</span>]</span>
<span id="cb15-6">  se_hat   <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>coefficients[<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;">"Std. Error"</span>]</span>
<span id="cb15-7">  z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> beta_hat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> se_hat</span>
<span id="cb15-8">  p_val <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pchisq</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="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</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;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb15-9">  GWAS_df[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;">c</span>(beta_hat, se_hat, z, p_val)</span>
<span id="cb15-10">}</span></code></pre></div></div>
</div>
<p>Plotting <code>-log10(pval)</code> against SNP position gives a regional Manhattan plot; the tallest peaks are candidate causal variants.</p>
<p><strong>Apply ABF fine-mapping</strong> using the Wakefield formula from Part 3, implemented as a reusable function:</p>
<div id="feeccf62" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:48.145871Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:48.144393Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:48.171895Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:48.170056Z&quot;}}" data-execution_count="11">
<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">run_abf <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>(beta, stderr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">W =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.04</span>) {</span>
<span id="cb16-2">  z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> beta <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> stderr</span>
<span id="cb16-3">  V <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> stderr<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="cb16-4">  r <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> (W <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> V)</span>
<span id="cb16-5">  lbf <span class="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>(<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> r<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="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;">2</span></span>
<span id="cb16-6">  lbf_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>(lbf)</span>
<span id="cb16-7">  denom <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lbf_max <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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(lbf <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> lbf_max)))</span>
<span id="cb16-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(lbf <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> denom)</span>
<span id="cb16-9">}</span>
<span id="cb16-10"></span>
<span id="cb16-11">GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PIP_ABF <span class="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_abf</span>(GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>beta, GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>se)</span></code></pre></div></div>
</div>
<p>ABF will often strongly prioritize just one signal, even when several causal variants exist.</p>
<p><strong>Run SuSiE</strong>, using an in-sample LD matrix computed directly from the simulated genotypes:</p>
<div id="57eb231f" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:48.181309Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:48.180126Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:48.249492Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:48.247581Z&quot;}}" data-execution_count="12">
<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">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;">cov</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(X))</span>
<span id="cb17-2"></span>
<span id="cb17-3">susie_results <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">susie_rss</span>(</span>
<span id="cb17-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bhat =</span> GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>beta, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shat =</span> GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>se, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> N, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">R =</span> R,</span>
<span id="cb17-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var_y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(y), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">L =</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;">estimate_residual_variance =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb17-6">)</span>
<span id="cb17-7"></span>
<span id="cb17-8">GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PIP_SuSiE <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> susie_results<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pip</span>
<span id="cb17-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(GWAS_df[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">order</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>GWAS_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PIP_SuSiE), ])</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<div class="ansi-escaped-output">
<pre><span style="font-weight:bold;text-decoration:underline" class="ansi-magenta-fg">HINT:</span> For estimate_residual_variance = TRUE, please check that R is the "in-sample" LD matrix; that is, the correlation matrix obtained using the exact same data matrix X that was used for the other summary statistics. Also note, when covariates are included in the univariate regressions that produced the summary statistics, also consider removing these effects from X before computing R.


</pre>
</div>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">beta</th>
<th data-quarto-table-cell-role="th" scope="col">se</th>
<th data-quarto-table-cell-role="th" scope="col">z</th>
<th data-quarto-table-cell-role="th" scope="col">pval</th>
<th data-quarto-table-cell-role="th" scope="col">PIP_ABF</th>
<th data-quarto-table-cell-role="th" scope="col">PIP_SuSiE</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>-0.23391752</td>
<td>0.02955646</td>
<td>-7.914261</td>
<td>2.487253e-15</td>
<td>9.999993e-01</td>
<td>1.000000e+00</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">39</th>
<td>0.11271078</td>
<td>0.03016101</td>
<td>3.736970</td>
<td>1.862512e-04</td>
<td>4.604485e-11</td>
<td>1.000000e+00</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">68</th>
<td>-0.17209840</td>
<td>0.02969970</td>
<td>-5.794617</td>
<td>6.847711e-09</td>
<td>6.692374e-07</td>
<td>9.999861e-01</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">51</th>
<td>-0.11439249</td>
<td>0.03180954</td>
<td>-3.596169</td>
<td>3.229380e-04</td>
<td>2.881971e-11</td>
<td>2.692740e-06</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">48</th>
<td>-0.10034456</td>
<td>0.03015366</td>
<td>-3.327774</td>
<td>8.754293e-04</td>
<td>1.120259e-11</td>
<td>2.578888e-06</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">32</th>
<td>-0.08948059</td>
<td>0.03040323</td>
<td>-2.943127</td>
<td>3.249148e-03</td>
<td>3.467398e-12</td>
<td>1.484153e-06</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>A <code>PIP_SuSiE</code> plot typically shows several distinct peaks, corresponding to the multiple simulated causal variants — unlike ABF’s single dominant peak.</p>
<p><strong>Examine credible sets</strong>, the most important SuSiE output:</p>
<div id="f3e2778e" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:48.254009Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:48.252406Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:48.268480Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:48.267054Z&quot;}}" data-execution_count="13">
<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">susie_results<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sets<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cs</span>
<span id="cb18-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># $L1: 1    $L2: 39   $L3: 68</span></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<dl>
    <dt>$L1</dt>
        <dd>1</dd>
    <dt>$L2</dt>
        <dd>39</dd>
    <dt>$L3</dt>
        <dd>68</dd>
</dl>
</div>
</div>
<p>Three independent signals, correctly located at variants 39, 20, and 68.</p>
<section id="abf-vs.-susie-head-to-head" class="level2" data-number="4.1">
<h2 data-number="4.1" class="anchored" data-anchor-id="abf-vs.-susie-head-to-head"><span class="header-section-number">4.1</span> ABF vs.&nbsp;SuSiE, Head to Head</h2>
<p>Where ABF may identify only variant 1, SuSiE correctly recovers variants 1, 39, <em>and</em> 68 — because it allows multiple causal variants. This is precisely why SuSiE has become the preferred modern approach.</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSimulate%7D%20%5Crightarrow%20%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BABF%7D%20%5Crightarrow%20%5Ctext%7BPIP%20Estimates%7D%20%5Crightarrow%20%5Ctext%7BSuSiE%7D%20%5Crightarrow%20%5Ctext%7BMultiple%20Signals%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D%20%5Crightarrow%20%5Ctext%7BCandidate%20Causal%20Variants%7D"></p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> A complete fine-mapping analysis starts from GWAS summary statistics and an LD matrix. ABF converts these into posterior probabilities under a single-causal-variant assumption; SuSiE extends this to multiple independent signals in the same locus. The outputs — PIPs and credible sets — feed directly into downstream eQTL and colocalization analyses.</p>
</blockquote>
</section>
</section>
<section id="understanding-credible-sets-in-practice" class="level1" data-number="5">
<h1 data-number="5"><span class="header-section-number">5</span> Understanding Credible Sets in Practice</h1>
<p>After running SuSiE, researchers often jump straight to PIPs — but the most informative output is usually the <strong>credible set</strong> itself, since most real GWAS loci don’t resolve to a single variant.</p>
<section id="why-we-need-them" class="level2" data-number="5.1">
<h2 data-number="5.1" class="anchored" data-anchor-id="why-we-need-them"><span class="header-section-number">5.1</span> Why We Need Them</h2>
<p>A single SNP at PIP = 0.98 makes life easy. But most loci look more like:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>SNP</th>
<th>PIP</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>rs39</td>
<td>0.32</td>
</tr>
<tr class="even">
<td>rs40</td>
<td>0.28</td>
</tr>
<tr class="odd">
<td>rs41</td>
<td>0.22</td>
</tr>
<tr class="even">
<td>rs42</td>
<td>0.10</td>
</tr>
<tr class="odd">
<td>rs43</td>
<td>0.08</td>
</tr>
</tbody>
</table>
<p>Now which SNP is truly causal is genuinely unclear — rather than pretending to know, Bayesian fine-mapping represents that uncertainty explicitly via the credible set.</p>
<p>A <strong>95% credible set</strong> means there’s a 95% probability the causal SNP lies <em>somewhere in the set</em> — not a 95% probability attached to each member individually.</p>
</section>
<section id="worked-construction" class="level2" data-number="5.2">
<h2 data-number="5.2" class="anchored" data-anchor-id="worked-construction"><span class="header-section-number">5.2</span> Worked Construction</h2>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Step</th>
<th>Add</th>
<th>Cumulative</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1</td>
<td>rs39 (0.45)</td>
<td>0.45</td>
</tr>
<tr class="even">
<td>2</td>
<td>rs40 (0.25)</td>
<td>0.70</td>
</tr>
<tr class="odd">
<td>3</td>
<td>rs41 (0.15)</td>
<td>0.85</td>
</tr>
<tr class="even">
<td>4</td>
<td>rs42 (0.08)</td>
<td>0.93</td>
</tr>
<tr class="odd">
<td>5</td>
<td>rs43 (0.04)</td>
<td>0.97</td>
</tr>
</tbody>
</table>
<p>The 95% credible set = {rs39, rs40, rs41, rs42, rs43}. This does <strong>not</strong> mean all five are causal — it means one (or more) of them likely is, but the data can’t distinguish which.</p>
<p><strong>Resolution spectrum:</strong> ideal = {rs39} alone (excellent, near-certain localization); moderate = {rs39, rs40, rs41} (still useful — 3 variants to validate instead of 500); poor = 50–100 SNPs (data can’t isolate the causal variant at all).</p>
</section>
<section id="why-large-credible-sets-occur" class="level2" data-number="5.3">
<h2 data-number="5.3" class="anchored" data-anchor-id="why-large-credible-sets-occur"><span class="header-section-number">5.3</span> Why Large Credible Sets Occur</h2>
<ol type="1">
<li><strong>High LD</strong> — SNPs with <img src="https://latex.codecogs.com/png.latex?r%5E2%20%3E%200.95"> are statistically indistinguishable.</li>
<li><strong>Small sample size</strong> — less information, more diffuse PIPs, larger sets. (N=500 vs N=50,000 makes a dramatic difference.)</li>
<li><strong>Weak genetic effects</strong> — small <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> is harder to localize than large <img src="https://latex.codecogs.com/png.latex?%5Cbeta">.</li>
</ol>
<p><strong>Excellent fine-mapping:</strong> rs39 = 0.97, everything else ≈ 0.01 → credible set = {rs39}, near-perfect localization. <strong>Difficult fine-mapping:</strong> five SNPs each around 0.13–0.25 → credible set = all five, strong genuine uncertainty.</p>
</section>
<section id="multiple-credible-sets" class="level2" data-number="5.4">
<h2 data-number="5.4" class="anchored" data-anchor-id="multiple-credible-sets"><span class="header-section-number">5.4</span> Multiple Credible Sets</h2>
<p>Modern loci often contain multiple signals — Signal 1: CS1={rs20}, Signal 2: CS2={rs39, rs40}, Signal 3: CS3={rs68} — exactly what SuSiE was designed to discover. Each credible set corresponds to a separate causal signal:</p>
<div id="cc910417" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:48.273102Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:48.271400Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:48.286551Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:48.284787Z&quot;}}" data-execution_count="14">
<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">susie_results<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sets<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cs</span>
<span id="cb19-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># $L1: 1    $L2: 39   $L3: 68</span></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<dl>
    <dt>$L1</dt>
        <dd>1</dd>
    <dt>$L2</dt>
        <dd>39</dd>
    <dt>$L3</dt>
        <dd>68</dd>
</dl>
</div>
</div>
</section>
<section id="coverage-trade-off" class="level2" data-number="5.5">
<h2 data-number="5.5" class="anchored" data-anchor-id="coverage-trade-off"><span class="header-section-number">5.5</span> Coverage Trade-Off</h2>
<p>Most studies use 95% coverage, but 80%, 90%, and 99% are all used. Higher coverage (99%) gives more certainty but larger sets; lower coverage (80%) gives smaller sets but greater risk of missing the true causal SNP entirely.</p>
</section>
<section id="credible-sets-lead-snps" class="level2" data-number="5.6">
<h2 data-number="5.6" class="anchored" data-anchor-id="credible-sets-lead-snps"><span class="header-section-number">5.6</span> Credible Sets ≠ Lead SNPs</h2>
<p>A “lead SNP” (smallest p-value, or highest PIP) is a single point estimate; the credible set captures the uncertainty around it. These are not interchangeable, and conflating them is a common mistake.</p>
<p><strong>What a fine-mapping study should report:</strong> lead SNP, PIP, credible set, credible set size, method used, LD reference panel. Example:</p>
<blockquote class="blockquote">
<p>Lead variant rs39, PIP 0.94, 95% credible set {rs39, rs40}, size 2.</p>
</blockquote>
</section>
<section id="biological-interpretation" class="level2" data-number="5.7">
<h2 data-number="5.7" class="anchored" data-anchor-id="biological-interpretation"><span class="header-section-number">5.7</span> Biological Interpretation</h2>
<p>Credible set size = 1 → strong candidate for CRISPR/reporter/functional validation. Credible set size = 50 → needs more data (larger GWAS, better LD panel, eQTL analysis, colocalization, functional annotations) before it can be refined further.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Credible sets quantify uncertainty by reporting a group of variants that jointly contain the causal SNP with a specified probability (typically 95%), rather than pretending to identify a single answer. Small sets mean strong resolution; large sets reflect high LD, limited sample size, or weak effects. Credible sets are often more informative than lead SNPs precisely because they represent uncertainty explicitly.</p>
</blockquote>
</section>
</section>
<section id="the-impact-of-sample-size-effect-size-and-ld-on-resolution" class="level1" data-number="6">
<h1 data-number="6"><span class="header-section-number">6</span> The Impact of Sample Size, Effect Size, and LD on Resolution</h1>
<p>“Why is my credible set so large? Why are my PIPs so low? Why can’t I identify the causal SNP?” The answer almost always comes down to three factors: <strong>sample size</strong>, <strong>linkage disequilibrium</strong>, and <strong>effect size</strong>.</p>
<p><strong>Resolution</strong> refers to how precisely a causal variant can be localized. Excellent: 95% credible set = 1 SNP. Poor: 95% credible set = 50 SNPs. The goal is always small credible sets with high PIPs.</p>
<section id="factor-1-sample-size" class="level2" data-number="6.1">
<h2 data-number="6.1" class="anchored" data-anchor-id="factor-1-sample-size"><span class="header-section-number">6.1</span> Factor 1: Sample Size</h2>
<p>The single most important factor. Standard error scales as <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSE%7D%20%5Cpropto%201/%5Csqrt%7BN%7D">, so larger <img src="https://latex.codecogs.com/png.latex?N"> → smaller SE → larger Z-scores → higher PIPs.</p>
<p><strong>Example:</strong> true <img src="https://latex.codecogs.com/png.latex?%5Cbeta%20=%200.10">. At <img src="https://latex.codecogs.com/png.latex?N=500">: SE ≈ 0.08, Z ≈ 1.25 (weak evidence). At <img src="https://latex.codecogs.com/png.latex?N=50%7B,%7D000">: SE ≈ 0.01, Z ≈ 10 (very strong evidence). Increasing sample size 10× often improves fine-mapping resolution dramatically — sharper, less noisy signal, smaller credible sets.</p>
</section>
<section id="factor-2-linkage-disequilibrium" class="level2" data-number="6.2">
<h2 data-number="6.2" class="anchored" data-anchor-id="factor-2-linkage-disequilibrium"><span class="header-section-number">6.2</span> Factor 2: Linkage Disequilibrium</h2>
<p>Fine-mapping is easiest when SNPs are weakly correlated. At <img src="https://latex.codecogs.com/png.latex?r%5E2%20=%200.05">, each SNP behaves independently and a causal signal is easy to pinpoint. At <img src="https://latex.codecogs.com/png.latex?r%5E2%20=%200.99">, neighboring SNPs look almost statistically identical (e.g.&nbsp;rs39 at <img src="https://latex.codecogs.com/png.latex?p=1%5Ctimes10%5E%7B-12%7D"> and rs40 at <img src="https://latex.codecogs.com/png.latex?p=2%5Ctimes10%5E%7B-12%7D">) — the model simply cannot tell them apart, producing large credible sets.</p>
<p><strong>Resolution spectrum by LD:</strong> low LD → {rs39} (excellent); moderate LD → {rs39, rs40, rs41} (acceptable); very high LD → 25 SNPs (poor). Even a huge sample size (<img src="https://latex.codecogs.com/png.latex?N=100%7B,%7D000">) can’t fully overcome severe LD in a locus — more data helps, but doesn’t eliminate the fundamental statistical limitation.</p>
<p><strong>Ancestry matters here:</strong> European-ancestry LD blocks tend to be long (harder to resolve); African-ancestry LD blocks tend to be shorter (often better resolution) — one reason multi-ancestry fine-mapping has become popular.</p>
</section>
<section id="factor-3-effect-size" class="level2" data-number="6.3">
<h2 data-number="6.3" class="anchored" data-anchor-id="factor-3-effect-size"><span class="header-section-number">6.3</span> Factor 3: Effect Size</h2>
<p>Large effects (<img src="https://latex.codecogs.com/png.latex?%5Cbeta%20=%200.25">) → large Z-score → high PIP → often a single-SNP credible set. Small effects (<img src="https://latex.codecogs.com/png.latex?%5Cbeta%20=%200.01">) → small Z-score → diffuse PIPs → large credible set. Traits differ in genetic architecture: LDL cholesterol often has large-effect variants; educational attainment is dominated by tiny effects — so some traits are inherently easier to fine-map than others. Lower heritability (<img src="https://latex.codecogs.com/png.latex?h%5E2%20=%200.01"> vs.&nbsp;<img src="https://latex.codecogs.com/png.latex?0.10">) weakens signals the same way.</p>
</section>
<section id="interaction-between-factors" class="level2" data-number="6.4">
<h2 data-number="6.4" class="anchored" data-anchor-id="interaction-between-factors"><span class="header-section-number">6.4</span> Interaction Between Factors</h2>
<p><strong>Best case:</strong> large sample size + low LD + large effects → tiny credible sets, high PIPs. <strong>Worst case:</strong> small sample size + high LD + tiny effects → huge credible sets, low PIPs.</p>
</section>
<section id="diagnosing-poor-fine-mapping" class="level2" data-number="6.5">
<h2 data-number="6.5" class="anchored" data-anchor-id="diagnosing-poor-fine-mapping"><span class="header-section-number">6.5</span> Diagnosing Poor Fine-Mapping</h2>
<p>When results look weak, check: Is sample size large enough? Is LD too high? Are effect sizes too small? Is the LD reference panel the right ancestry?</p>
<p><strong>Common beginner mistake:</strong> interpreting a 50-SNP credible set as “fine-mapping failed.” Usually the method is working correctly — the data simply doesn’t contain enough information to distinguish the variants. Fine-mapping <em>quantifies</em> uncertainty; it doesn’t eliminate it.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Fine-mapping resolution is driven primarily by sample size, LD, and effect size. Larger samples and stronger effects sharpen PIPs; high LD makes neighboring variants statistically indistinguishable and enlarges credible sets. No method can fully overcome severe LD or limited information — understanding these limits is essential for realistic interpretation and avoiding overconfidence in causal variant claims.</p>
</blockquote>
</section>
</section>
<section id="fine-mapping-with-individual-level-data-vs.-summary-statistics" class="level1" data-number="7">
<h1 data-number="7"><span class="header-section-number">7</span> Fine-Mapping with Individual-Level Data vs.&nbsp;Summary Statistics</h1>
<p>The first question in any fine-mapping project is: what data do I actually have? The answer determines which methods you can use, how accurate your results will be, how LD gets estimated, and whether colocalization is even possible.</p>
<section id="two-main-types-of-data" class="level2" data-number="7.1">
<h2 data-number="7.1" class="anchored" data-anchor-id="two-main-types-of-data"><span class="header-section-number">7.1</span> Two Main Types of Data</h2>
<p><strong>Individual-level data</strong> — genotypes, phenotypes, and covariates per person:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Person</th>
<th>SNP1</th>
<th>SNP2</th>
<th>SNP3</th>
<th>Phenotype</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3.2</td>
</tr>
<tr class="even">
<td>2</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1.7</td>
</tr>
<tr class="odd">
<td>3</td>
<td>2</td>
<td>0</td>
<td>1</td>
<td>4.5</td>
</tr>
</tbody>
</table>
<p><strong>Summary statistics only</strong> — no individual genotypes:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>SNP</th>
<th>Beta</th>
<th>SE</th>
<th>P-value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>rs1</td>
<td>0.12</td>
<td>0.03</td>
<td>1e-8</td>
</tr>
<tr class="even">
<td>rs2</td>
<td>0.10</td>
<td>0.03</td>
<td>5e-7</td>
</tr>
<tr class="odd">
<td>rs3</td>
<td>0.02</td>
<td>0.04</td>
<td>0.40</td>
</tr>
</tbody>
</table>
<p>Large biobanks (UK Biobank, FinnGen, deCODE, iPSYCH) usually release only summary statistics — raw genotype sharing raises privacy, storage, and regulatory concerns.</p>
</section>
<section id="individual-level-data-workflow-gold-standard" class="level2" data-number="7.2">
<h2 data-number="7.2" class="anchored" data-anchor-id="individual-level-data-workflow-gold-standard"><span class="header-section-number">7.2</span> Individual-Level Data Workflow (Gold Standard)</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BRaw%20Genotypes%7D%20%5Crightarrow%20%5Ctext%7BQC%7D%20%5Crightarrow%20%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BCompute%20In-Sample%20LD%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D"></p>
<div id="34ea61d6" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T18:27:48.291026Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T18:27:48.289421Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T18:27:48.331758Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T18:27:48.329293Z&quot;}}" data-execution_count="15">
<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">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;">cov</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(X))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># X = genotype matrix from your own samples</span></span></code></pre></div></div>
</div>
<p>This produces <strong>in-sample LD</strong> — LD computed from exactly the individuals in your GWAS — the most accurate LD possible, and considered the gold standard.</p>
</section>
<section id="summary-statistics-workflow" class="level2" data-number="7.3">
<h2 data-number="7.3" class="anchored" data-anchor-id="summary-statistics-workflow"><span class="header-section-number">7.3</span> Summary Statistics Workflow</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSummary%20Statistics%7D%20%5Crightarrow%20%5Ctext%7BExternal%20LD%20Panel%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D"></p>
<p>Common reference panels: 1000 Genomes, UK Biobank, TOPMed, HRC. You must match the reference panel’s ancestry to your GWAS cohort — e.g.&nbsp;European-ancestry GWAS → 1000 Genomes Europeans.</p>
</section>
<section id="why-ld-matching-is-critical" class="level2" data-number="7.4">
<h2 data-number="7.4" class="anchored" data-anchor-id="why-ld-matching-is-critical"><span class="header-section-number">7.4</span> Why LD Matching Is Critical</h2>
<p>If your GWAS is Finnish but you estimate LD from an African-ancestry panel, the LD structure will genuinely differ — e.g.&nbsp;true GWAS LD between rs39/rs40 might be <img src="https://latex.codecogs.com/png.latex?r%5E2=0.95"> while the mismatched reference shows <img src="https://latex.codecogs.com/png.latex?r%5E2=0.30">. That mismatch can cause false signals, incorrect PIPs, wrong credible sets, and failed colocalization — one of the most common causes of unreliable fine-mapping. SuSiE in particular needs good LD, since it relies on knowing exactly which SNPs are correlated to separate multiple signals.</p>
<p><strong>Methods requiring LD:</strong> SuSiE, FINEMAP, CAVIAR, CARMA. <strong>Methods that don’t:</strong> ABF (needs only beta and SE) — one reason it remains useful as a fallback.</p>
</section>
<section id="single-cohort-vs.-meta-analysis" class="level2" data-number="7.5">
<h2 data-number="7.5" class="anchored" data-anchor-id="single-cohort-vs.-meta-analysis"><span class="header-section-number">7.5</span> Single-Cohort vs.&nbsp;Meta-Analysis</h2>
<p><strong>Single-cohort</strong> (e.g.&nbsp;FinnGen or UK Biobank alone): ancestry-matched LD → fine-mapping is generally straightforward.</p>
<p><strong>Meta-analysis</strong> (European + Finnish + Japanese + African cohorts combined): each cohort has different LD, so a single LD matrix no longer represents the pooled data accurately. This motivated specialized meta-analysis methods. Common strategies: fine-map each cohort separately then compare/integrate results, or use methods purpose-built for heterogeneous LD (FastMap and related approaches).</p>
</section>
<section id="multi-ancestry-fine-mapping" class="level2" data-number="7.6">
<h2 data-number="7.6" class="anchored" data-anchor-id="multi-ancestry-fine-mapping"><span class="header-section-number">7.6</span> Multi-Ancestry Fine-Mapping</h2>
<p>Different populations have different LD block lengths — combining ancestries can dramatically improve resolution, since a variant tightly linked to several others in a European LD block might sit alone in an African LD block. Example: a European-only GWAS gives a credible set of 40 SNPs, but adding African-ancestry data narrows it to 5.</p>
</section>
<section id="data-type-ranking" class="level2" data-number="7.7">
<h2 data-number="7.7" class="anchored" data-anchor-id="data-type-ranking"><span class="header-section-number">7.7</span> Data-Type Ranking</h2>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Tier</th>
<th>Data</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Best</td>
<td>Individual-level data + in-sample LD</td>
</tr>
<tr class="even">
<td>Good</td>
<td>Summary statistics + matched LD panel</td>
</tr>
<tr class="odd">
<td>Risky</td>
<td>Summary statistics + poorly matched LD</td>
</tr>
<tr class="even">
<td>Worst</td>
<td>Summary statistics + no LD information</td>
</tr>
</tbody>
</table>
<p><strong>Practical advice:</strong> use in-sample LD whenever possible; always match ancestry between GWAS and LD panel; avoid mixing populations unless using methods explicitly designed for multi-ancestry analysis.</p>
<p>This all matters even more for colocalization later: <code>coloc.susie</code> depends on accurate fine-mapping, and poor LD estimation can cause both false and missed colocalization. <strong>Good LD = good fine-mapping = good colocalization.</strong></p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Data availability determines your entire fine-mapping strategy. Individual-level data gives the best results because LD is computed directly from the study sample. Summary-statistics-only analyses require an external, ancestry-matched LD reference panel — mismatch here is one of the most common sources of unreliable results in modern fine-mapping.</p>
</blockquote>
</section>
</section>
<section id="major-fine-mapping-methods-abf-caviar-finemap-susie-carma-fastmap" class="level1" data-number="8">
<h1 data-number="8"><span class="header-section-number">8</span> Major Fine-Mapping Methods — ABF, CAVIAR, FINEMAP, SuSiE, CARMA, FastMap</h1>
<p>The core concepts (LD, PIPs, credible sets, Bayesian inference, multiple causal variants) are now in place — the natural next question is which method to actually use. Choice depends on available data, LD information, study design, and computational resources.</p>
<p><strong>Historical evolution:</strong> <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BABF%7D%20%5Crightarrow%20%5Ctext%7BCAVIAR%7D%20%5Crightarrow%20%5Ctext%7BFINEMAP%7D%20%5Crightarrow%20%5Ctext%7BSuSiE%7D%20%5Crightarrow%20%5Ctext%7BCARMA%7D%20%5Crightarrow%20%5Ctext%7BFastMap%7D"> — each generation addressed limitations of the last.</p>
<table class="caption-top table">
<colgroup>
<col style="width: 16%">
<col style="width: 16%">
<col style="width: 16%">
<col style="width: 16%">
<col style="width: 16%">
<col style="width: 16%">
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Main idea</th>
<th>Inputs</th>
<th>Multiple signals?</th>
<th>Needs LD?</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>ABF</strong></td>
<td>Assume one causal variant; compute Bayes Factors per SNP, normalize to posteriors</td>
<td>Beta, SE</td>
<td>No</td>
<td>No</td>
<td>Fast, simple, minimal inputs; can’t separate multiple signals; best when no trustworthy LD exists or for quick exploratory passes. Basis of <code>coloc.abf</code>.</td>
</tr>
<tr class="even">
<td><strong>CAVIAR</strong></td>
<td>Models several causal SNPs simultaneously via Z-scores + LD</td>
<td>Z-scores, LD matrix</td>
<td>Yes</td>
<td>Yes</td>
<td>One of the first methods beyond ABF; accounts for LD and multiple variants, but computationally expensive in large regions. Historically important — inspired later methods.</td>
</tr>
<tr class="odd">
<td><strong>FINEMAP</strong></td>
<td>Bayesian model selection: searches causal-variant <em>configurations</em> (e.g.&nbsp;{rs39}, {rs20+rs39}, {rs20+rs39+rs68}) and finds which best explains the data</td>
<td>Summary statistics, LD matrix</td>
<td>Yes</td>
<td>Yes</td>
<td>Fast, accurate, scalable for large GWAS/biobank studies; widely used; needs good LD or performance degrades.</td>
</tr>
<tr class="even">
<td><strong>SuSiE</strong></td>
<td>Sum of single effects — models phenotype as several independent signals rather than one</td>
<td>Summary statistics + LD, or individual-level data</td>
<td>Yes</td>
<td>Yes</td>
<td>Excellent multiple-signal handling, interpretable credible sets, computationally efficient, integrates naturally with colocalization. Sensitive to LD mismatch. The current default for most researchers.</td>
</tr>
<tr class="odd">
<td><strong>CARMA</strong></td>
<td><em>CAusal variant identification with Allelic heterogeneity and outliers</em> — explicitly models outlier/artifact SNPs (genotyping errors, imputation artifacts)</td>
<td>Summary statistics, LD matrix</td>
<td>Yes</td>
<td>Yes</td>
<td>Robust to problematic data; more computationally intensive and harder to interpret. Best for uncertain data quality or large meta-analyses prone to artifacts.</td>
</tr>
<tr class="even">
<td><strong>FastMap</strong></td>
<td>Efficient approximations built for biobank-scale data (millions of individuals, thousands of loci)</td>
<td>Summary statistics, LD</td>
<td>Yes</td>
<td>Yes</td>
<td>Very fast, highly scalable; newer and less extensively validated than SuSiE/FINEMAP. Best for massive biobank or meta-analysis fine-mapping.</td>
</tr>
</tbody>
</table>
<section id="choosing-a-method" class="level2" data-number="8.1">
<h2 data-number="8.1" class="anchored" data-anchor-id="choosing-a-method"><span class="header-section-number">8.1</span> Choosing a Method</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Your situation</th>
<th>Recommended method</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Only beta/SE, no LD matrix</td>
<td>ABF</td>
</tr>
<tr class="even">
<td>Summary statistics + good LD</td>
<td>SuSiE or FINEMAP</td>
</tr>
<tr class="odd">
<td>Suspected outliers/artifacts</td>
<td>CARMA</td>
</tr>
<tr class="even">
<td>Very large-scale (biobank) analysis</td>
<td>FastMap</td>
</tr>
<tr class="odd">
<td>Planning colocalization afterward</td>
<td>SuSiE (integrates with <code>coloc.susie</code>)</td>
</tr>
</tbody>
</table>
<p><strong>Current consensus:</strong> ask most statistical geneticists for the default fine-mapping method today and the answer is <strong>SuSiE</strong> — it offers multi-signal modeling, credible sets, PIPs, strong theoretical grounding, and mature software support. FINEMAP remains extremely popular too, often run alongside SuSiE.</p>
<p><strong>Practical recommendation summary:</strong> individual-level data → SuSiE; summary statistics + good LD → SuSiE or FINEMAP; no LD available → ABF; suspected data artifacts → CARMA; massive biobank analyses → FastMap.</p>
<p>All these methods answer the same underlying question — “which variants are most likely causal?” — differing mainly in their assumptions, computational strategy, treatment of multiple signals, and robustness to imperfect data. The shared output vocabulary — PIPs and credible sets — is the common language of modern fine-mapping.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> ABF is simple and useful without LD but assumes a single causal variant. CAVIAR pioneered multi-variant modeling. FINEMAP and SuSiE are the current workhorses for multi-signal fine-mapping with credible sets. CARMA adds robustness to outliers; FastMap trades some validation maturity for speed at biobank scale. In practice, SuSiE and FINEMAP dominate when reliable LD is available.</p>
</blockquote>
</section>
</section>
<section id="the-fine-mapping-decision-tree-choosing-the-correct-pipeline" class="level1" data-number="9">
<h1 data-number="9"><span class="header-section-number">9</span> The Fine-Mapping Decision Tree — Choosing the Correct Pipeline</h1>
<p>For beginners, the hard part isn’t running fine-mapping software — it’s choosing the right workflow before you even start. Rather than picking a method first, start by asking: <strong>what data do we actually have?</strong></p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BAvailable%20Data%7D%20%5Crightarrow%20%5Ctext%7BAppropriate%20LD%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%20Method%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D%20%5Crightarrow%20%5Ctext%7BBiological%20Interpretation%7D"></p>
<section id="step-1-do-you-have-individual-level-data" class="level2" data-number="9.1">
<h2 data-number="9.1" class="anchored" data-anchor-id="step-1-do-you-have-individual-level-data"><span class="header-section-number">9.1</span> Step 1: Do You Have Individual-Level Data?</h2>
<p>That means genotypes and phenotypes for each participant — PLINK files (<code>.bed</code>/<code>.bim</code>/<code>.fam</code>) or VCF + phenotype files. If yes, follow <strong>Branch A</strong>; if no, follow <strong>Branch B</strong>.</p>
</section>
<section id="branch-a-individual-level-data" class="level2" data-number="9.2">
<h2 data-number="9.2" class="anchored" data-anchor-id="branch-a-individual-level-data"><span class="header-section-number">9.2</span> Branch A: Individual-Level Data</h2>
<p>The ideal case (UK Biobank, FinnGen, iPSYCH, All of Us, when individual-level access is granted) — you can compute <strong>in-sample LD</strong> directly:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BIndividual-Level%20Data%7D%20%5Crightarrow%20%5Ctext%7BQC%7D%20%5Crightarrow%20%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BCompute%20In-Sample%20LD%7D%20%5Crightarrow%20%5Ctext%7BSuSiE%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D"></p>
<p><strong>Single cohort:</strong> straightforward — in-sample LD, then SuSiE. <strong>Multiple cohorts</strong> (European + African + Asian, each with full genotypes): either (1) fine-map each cohort separately then compare — often recommended — or (2) run multi-ancestry fine-mapping, since differing LD structures across ancestries can improve resolution.</p>
</section>
<section id="branch-b-summary-statistics-only" class="level2" data-number="9.3">
<h2 data-number="9.3" class="anchored" data-anchor-id="branch-b-summary-statistics-only"><span class="header-section-number">9.3</span> Branch B: Summary Statistics Only</h2>
<p>Most researchers land here. The critical follow-up question: <strong>is a reliable, ancestry-matched LD panel available?</strong></p>
<ul>
<li><strong>B1 — good LD available:</strong> match ancestry between GWAS and reference panel (mismatch distorts PIPs and credible sets) → use SuSiE or FINEMAP.</li>
<li><strong>B2 — no reliable LD:</strong> SuSiE/FINEMAP aren’t appropriate without LD → fall back to <strong>ABF</strong>, accepting its single-causal-variant assumption as a compromise: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSummary%20Statistics%7D%20%5Crightarrow%20%5Ctext%7BABF%7D%20%5Crightarrow%20%5Ctext%7BPosterior%20Probabilities%7D">.</li>
<li><strong>B3 — suspected data problems</strong> (imputation errors, outliers, meta-analysis artifacts): <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSummary%20Statistics%7D%20%5Crightarrow%20%5Ctext%7BLD%20Panel%7D%20%5Crightarrow%20%5Ctext%7BCARMA%7D">, built specifically for robustness to problematic variants.</li>
</ul>
</section>
<section id="the-meta-analysis-branch" class="level2" data-number="9.4">
<h2 data-number="9.4" class="anchored" data-anchor-id="the-meta-analysis-branch"><span class="header-section-number">9.4</span> The Meta-Analysis Branch</h2>
<p>Combining cohorts (UK Biobank + FinnGen + deCODE + Biobank Japan) into one meta-analysis means multiple LD structures exist simultaneously — but fine-mapping methods assume <em>one</em> LD matrix, creating a mismatch. Two strategies: (1) cohort-specific fine-mapping — fine-map FinnGen, UK Biobank, and deCODE separately, then integrate; often preferred — or (2) specialized meta-analysis methods like FastMap, designed to account for heterogeneous LD.</p>
</section>
<section id="the-colocalization-branch" class="level2" data-number="9.5">
<h2 data-number="9.5" class="anchored" data-anchor-id="the-colocalization-branch"><span class="header-section-number">9.5</span> The Colocalization Branch</h2>
<p>Once you have a GWAS credible set and an eQTL credible set in the same region, the next question is whether they share a causal variant. If you used ABF → <code>coloc.abf</code> (<img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%7D%20+%20%5Ctext%7BeQTL%20summary%20stats%7D%20%5Crightarrow%20%5Ctext%7Bcoloc.abf%7D">, single-variant assumption). If you used SuSiE → <code>coloc.susie</code> (<img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%20fine-mapping%7D%20+%20%5Ctext%7BeQTL%20fine-mapping%7D%20%5Crightarrow%20%5Ctext%7Bcoloc.susie%7D">), generally preferred since it allows multiple causal variants and aligns naturally with modern fine-mapping.</p>
</section>
<section id="the-complete-decision-tree" class="level2" data-number="9.6">
<h2 data-number="9.6" class="anchored" data-anchor-id="the-complete-decision-tree"><span class="header-section-number">9.6</span> The Complete Decision Tree</h2>
<pre><code>Individual-level data?
 ├─ Yes → Compute in-sample LD → SuSiE
 └─ No  → Summary statistics → Good LD available?
              ├─ Yes → SuSiE / FINEMAP
              └─ No  → ABF
                          ↓
                   Credible Sets → Colocalization
                                      ├─ coloc.abf
                                      └─ coloc.susie</code></pre>
</section>
<section id="worked-examples" class="level2" data-number="9.7">
<h2 data-number="9.7" class="anchored" data-anchor-id="worked-examples"><span class="header-section-number">9.7</span> Worked Examples</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th>Scenario</th>
<th>Data</th>
<th>Recommendation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>FinnGen study</td>
<td>Summary stats + FinnGen LD panel</td>
<td>SuSiE</td>
</tr>
<tr class="even">
<td>Public GWAS Catalog result</td>
<td>Beta + SE only, no LD</td>
<td>ABF</td>
</tr>
<tr class="odd">
<td>UK Biobank genotypes</td>
<td>Individual-level data</td>
<td>In-sample LD → SuSiE</td>
</tr>
<tr class="even">
<td>Psychiatric Genomics Consortium meta-analysis</td>
<td>Multi-cohort meta-analysis</td>
<td>Cohort-specific fine-mapping, or FastMap</td>
</tr>
</tbody>
</table>
<p><strong>Common beginner mistake:</strong> picking a method (SuSiE, say) before checking whether the required inputs (a trustworthy LD matrix) actually exist. Always start from the data you have, not the method you’ve heard of.</p>
<p><strong>Recommended default workflow:</strong> check for individual-level data first; if unavailable, check for a matched LD panel; if that’s also unavailable, use ABF as a fallback; treat CARMA and FastMap as targeted solutions for artifact-prone or biobank-scale data respectively.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> The correct fine-mapping pipeline is determined by data type, not by method popularity. Individual-level data → in-sample LD → SuSiE is the gold-standard path. Summary-statistics-only analyses hinge on whether a well-matched LD reference panel exists; without one, ABF is the fallback. Meta-analyses and suspected data-quality issues call for specialized approaches (FastMap, CARMA respectively). This decision tree should be the first step of any fine-mapping project, before any software is run.</p>
</blockquote>
</section>
</section>
<section id="integrating-fine-mapping-with-eqtl-data-identifying-candidate-genes" class="level1" data-number="10">
<h1 data-number="10"><span class="header-section-number">10</span> Integrating Fine-Mapping with eQTL Data — Identifying Candidate Genes</h1>
<p>Fine-mapping narrows a locus down to a small set of candidate causal SNPs — but it doesn’t tell us <em>which gene</em> is affected. Most GWAS hits are non-coding, often sitting 50–100 kb from the nearest gene, so proximity alone doesn’t reveal the mechanism. This is where <strong>eQTL</strong> (expression quantitative trait locus) analysis comes in.</p>
<section id="what-is-an-eqtl" class="level2" data-number="10.1">
<h2 data-number="10.1" class="anchored" data-anchor-id="what-is-an-eqtl"><span class="header-section-number">10.1</span> What Is an eQTL?</h2>
<p>A genetic variant that influences gene expression: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGenotype%7D%20%5Crightarrow%20%5Ctext%7BGene%20Expression%7D%20%5Crightarrow%20%5Ctext%7BDisease%20Risk%7D">. For example, rs12345 might increase expression of Gene A while decreasing expression of Gene B — creating a biological mechanism linking DNA variation to disease.</p>
<p><strong>Why this matters:</strong> suppose a schizophrenia GWAS finds rs12345 with PIP = 0.95 — excellent fine-mapping, but we still don’t know which gene is responsible. If rs12345 also turns out to be an eQTL for <em>CACNA1C</em>, we now have a concrete hypothesis: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVariant%7D%20%5Crightarrow%20%5Ctextit%7BCACNA1C%7D%20%5Ctext%7B%20Expression%7D%20%5Crightarrow%20%5Ctext%7BDisease%20Risk%7D">.</p>
<p><strong>Data sources:</strong> GTEx, the eQTL Catalogue, PsychENCODE, CommonMind Consortium, eQTLGen.</p>
<p><strong>Cis- vs.&nbsp;trans-eQTLs:</strong> most studies focus on <em>cis</em>-eQTLs (variant within ~1 Mb of the gene it regulates); <em>trans</em>-eQTLs (a chromosome 1 SNP affecting a chromosome 12 gene, say) are generally harder to detect.</p>
</section>
<section id="the-fine-mapping-eqtl-workflow" class="level2" data-number="10.2">
<h2 data-number="10.2" class="anchored" data-anchor-id="the-fine-mapping-eqtl-workflow"><span class="header-section-number">10.2</span> The Fine-Mapping + eQTL Workflow</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BCandidate%20SNPs%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Database%7D%20%5Crightarrow%20%5Ctext%7BCandidate%20Genes%7D"></p>
<p>Suppose fine-mapping gives a 95% credible set of {rs39, rs40, rs41}. Checking an eQTL database might show rs39 → Gene A, rs40 → no eQTL, rs41 → Gene B — immediately turning two SNPs into two strong gene candidates. Fine-mapping first is essential: starting from 1,000 raw GWAS SNPs and checking eQTLs for all of them would produce an unmanageable number of candidate genes; narrowing to 5 SNPs first makes the eQTL lookup tractable.</p>
<p><strong>The “nearest gene” trap:</strong> a common beginner mistake is assuming the nearest gene is the causal gene. It often isn’t — a GWAS SNP may sit near Gene A but actually regulate Gene B much farther away. eQTL data resolve this ambiguity.</p>
</section>
<section id="fine-mapping-the-eqtl-itself" class="level2" data-number="10.3">
<h2 data-number="10.3" class="anchored" data-anchor-id="fine-mapping-the-eqtl-itself"><span class="header-section-number">10.3</span> Fine-Mapping the eQTL Itself</h2>
<p>eQTL studies can (and should) be fine-mapped the same way GWAS is: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BExpression%20Trait%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Mapping%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Credible%20Sets%7D">. If GWAS fine-mapping gives CS = {rs39} <em>and</em> eQTL fine-mapping independently gives CS = {rs39}, that’s highly suggestive — both analyses point at the same variant, though it’s not yet proof (that requires formal colocalization, Part 12).</p>
</section>
<section id="tissue-specificity" class="level2" data-number="10.4">
<h2 data-number="10.4" class="anchored" data-anchor-id="tissue-specificity"><span class="header-section-number">10.4</span> Tissue Specificity</h2>
<p>A variant may be an eQTL in brain but not in blood or liver. For schizophrenia, relevant tissues include prefrontal cortex, hippocampus, and neurons — brain eQTLs are typically far more informative than blood eQTLs for a brain-relevant trait. A standard psychiatric-genomics workflow: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSchizophrenia%20GWAS%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BPsychENCODE%20eQTLs%7D%20%5Crightarrow%20%5Ctext%7BCandidate%20Gene%7D">.</p>
</section>
<section id="fine-mapping-eqtl-gene-prioritization" class="level2" data-number="10.5">
<h2 data-number="10.5" class="anchored" data-anchor-id="fine-mapping-eqtl-gene-prioritization"><span class="header-section-number">10.5</span> Fine-Mapping + eQTL = Gene Prioritization</h2>
<p>Fine-mapping answers “which SNP?”; eQTL analysis answers “which gene?” Together they give <strong>gene prioritization</strong> — but even when a GWAS SNP and an eQTL SNP look similar, that alone doesn’t prove they’re the <em>same</em> causal variant, because LD can create misleading overlap. That gap is exactly what <strong>colocalization</strong> (Part 12) formally resolves.</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Set%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Lookup%7D%20%5Crightarrow%20%5Ctext%7BCandidate%20Gene%7D%20%5Crightarrow%20%5Ctext%7BColocalization%7D%20%5Crightarrow%20%5Ctext%7BShared%20Causal%20Variant?%7D%20%5Crightarrow%20%5Ctext%7BBiological%20Mechanism%7D"></p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Fine-mapping identifies likely causal variants but not the affected gene. eQTL analysis fills that gap by linking variants to gene expression. Intersecting fine-mapped GWAS credible sets with eQTL results prioritizes candidate genes and generates mechanistic hypotheses — but overlap alone doesn’t prove a shared causal variant, since LD can create misleading co-occurrence. That limitation motivates formal colocalization methods.</p>
</blockquote>
</section>
</section>
<section id="colocalization-does-a-gwas-signal-share-a-causal-variant-with-an-eqtl-signal" class="level1" data-number="11">
<h1 data-number="11"><span class="header-section-number">11</span> Colocalization — Does a GWAS Signal Share a Causal Variant With an eQTL Signal?</h1>
<p>A GWAS signal and an eQTL signal overlapping in the same region doesn’t necessarily mean the same variant drives both. <strong>Colocalization</strong> is the formal statistical test for whether two association signals are driven by the same underlying causal variant.</p>
<p><strong>The ambiguity:</strong> suppose a schizophrenia GWAS implicates rs39, and an eQTL study implicates rs40 for Gene A expression, with <img src="https://latex.codecogs.com/png.latex?r%5E2(%5Ctext%7Brs39%7D,%20%5Ctext%7Brs40%7D)%20=%200.95">. Two explanations are equally consistent with strong LD alone:</p>
<ul>
<li><strong>Shared causal variant</strong> (true colocalization): rs39 drives both Gene A expression <em>and</em> disease risk directly.</li>
<li><strong>Distinct variants</strong> (not colocalization): rs39 drives disease risk, rs40 (a different variant) drives Gene A expression — strong LD just makes them look similar.</li>
</ul>
<section id="the-five-colocalization-hypotheses" class="level2" data-number="11.1">
<h2 data-number="11.1" class="anchored" data-anchor-id="the-five-colocalization-hypotheses"><span class="header-section-number">11.1</span> The Five Colocalization Hypotheses</h2>
<p>The <code>coloc</code> framework evaluates five mutually exclusive hypotheses, with posterior probabilities PP.H0–PP.H4 summing to 1:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Hypothesis</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>H0</td>
<td>No association with either trait</td>
</tr>
<tr class="even">
<td>H1</td>
<td>Association with Trait 1 (GWAS) only</td>
</tr>
<tr class="odd">
<td>H2</td>
<td>Association with Trait 2 (eQTL) only</td>
</tr>
<tr class="even">
<td>H3</td>
<td>Both traits associated, but <strong>different</strong> causal variants (“linkage”)</td>
</tr>
<tr class="odd">
<td>H4</td>
<td>Both traits associated, <strong>one shared</strong> causal variant — the result most researchers hope for</td>
</tr>
</tbody>
</table>
<p><strong>Example:</strong> PP.H0=0.00, PP.H1=0.00, PP.H2=0.01, PP.H3=0.05, PP.H4=0.94 → 94% probability of a shared causal variant, strong evidence for colocalization.</p>
<p><strong>Interpreting PP.H4:</strong> &gt;0.80 strong evidence, &gt;0.90 very strong, &gt;0.95 extremely strong. Conversely, PP.H3 = 0.95 means both traits are genuinely associated, but through <em>different</em> variants — a very different biological conclusion.</p>
</section>
<section id="coloc.abf" class="level2" data-number="11.2">
<h2 data-number="11.2" class="anchored" data-anchor-id="coloc.abf"><span class="header-section-number">11.2</span> <code>coloc.abf</code></h2>
<p>The original method — summary-statistics only, no LD matrix required. Inputs: beta, SE, and sample size for both traits. <strong>Major assumption:</strong> one causal variant per locus — the same limitation as ABF fine-mapping. This becomes a real problem when a locus genuinely has multiple signals: in one demonstration, a GWAS causal variant (39) overlapped an eQTL locus with <em>two</em> signals (39, shared, and 20, private) — <code>coloc.abf</code> strongly favored H3 (different variants) even though a shared variant truly existed, because it could only test one variant at a time.</p>
</section>
<section id="coloc.susie" class="level2" data-number="11.3">
<h2 data-number="11.3" class="anchored" data-anchor-id="coloc.susie"><span class="header-section-number">11.3</span> <code>coloc.susie</code></h2>
<p>Built to fix exactly this: instead of comparing one signal against one signal, it compares credible set against credible set (CS1 vs CS1, CS2 vs CS2, …), using SuSiE fine-mapping results from both traits. Workflow: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BSuSiE%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BeQTL%7D%20%5Crightarrow%20%5Ctext%7BSuSiE%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D">, both feeding into <code>coloc.susie</code>. In the same multi-signal example, <code>coloc.susie</code> correctly recovers PP.H4 ≈ 1.0 for the shared signal — advantages: handles multiple causal variants, is credible-set aware, and works on complex loci. This makes it the modern preferred choice whenever reliable LD is available.</p>
</section>
<section id="biological-interpretation-and-its-limits" class="level2" data-number="11.4">
<h2 data-number="11.4" class="anchored" data-anchor-id="biological-interpretation-and-its-limits"><span class="header-section-number">11.4</span> Biological Interpretation and Its Limits</h2>
<p>If a GWAS colocalizes with brain eQTL data for <em>CACNA1C</em> at PP.H4 = 0.97, that’s strong evidence the same variant influences both <em>CACNA1C</em> expression and disease risk — a compelling mechanistic hypothesis. But even PP.H4 = 0.99 does <strong>not</strong> prove causality — it only means the data are consistent with one shared variant. Confirming the mechanism still requires functional studies, CRISPR experiments, or animal models.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Colocalization formally tests whether two association signals share a causal variant, via five posterior probabilities (H0–H4), with H4 = shared variant and H3 = distinct variants. <code>coloc.abf</code> needs only summary statistics but assumes one causal variant per locus; <code>coloc.susie</code> overcomes this by comparing fine-mapped credible sets and is now the preferred default when good LD is available. Colocalization bridges GWAS findings to gene regulatory mechanisms — but even strong PP.H4 is evidence, not proof, of a causal mechanism.</p>
</blockquote>
</section>
</section>
<section id="practical-interpretation-of-colocalization-results" class="level1" data-number="12">
<h1 data-number="12"><span class="header-section-number">12</span> Practical Interpretation of Colocalization Results</h1>
<p>Running a colocalization analysis is easy; interpreting it correctly is much harder. Seeing PP.H4 = 0.85 and immediately concluding “gene identified!” skips several important checks.</p>
<section id="worked-examples-1" class="level2" data-number="12.1">
<h2 data-number="12.1" class="anchored" data-anchor-id="worked-examples-1"><span class="header-section-number">12.1</span> Worked Examples</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 14%">
<col style="width: 14%">
<col style="width: 14%">
<col style="width: 14%">
<col style="width: 14%">
<col style="width: 14%">
<col style="width: 14%">
</colgroup>
<thead>
<tr class="header">
<th>Scenario</th>
<th>PP.H0</th>
<th>PP.H1</th>
<th>PP.H2</th>
<th>PP.H3</th>
<th>PP.H4</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Strong colocalization</td>
<td>0.00</td>
<td>0.01</td>
<td>0.02</td>
<td>0.03</td>
<td>0.94</td>
<td>Very strong evidence for a shared causal variant — textbook success</td>
</tr>
<tr class="even">
<td>Strong evidence <em>against</em> colocalization</td>
<td>0.00</td>
<td>0.00</td>
<td>0.00</td>
<td>0.96</td>
<td>0.04</td>
<td>Both traits associated, but different variants — one of the most common real-world outcomes</td>
</tr>
<tr class="odd">
<td>Ambiguous region</td>
<td>0.05</td>
<td>0.10</td>
<td>0.10</td>
<td>0.35</td>
<td>0.40</td>
<td>Inconclusive — neither H3 nor H4 dominates; more data needed</td>
</tr>
</tbody>
</table>
</section>
<section id="conventional-thresholds" class="level2" data-number="12.2">
<h2 data-number="12.2" class="anchored" data-anchor-id="conventional-thresholds"><span class="header-section-number">12.2</span> Conventional Thresholds</h2>
<table class="caption-top table">
<thead>
<tr class="header">
<th>PP.H4</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>&lt; 0.50</td>
<td>Weak</td>
</tr>
<tr class="even">
<td>0.50–0.80</td>
<td>Moderate</td>
</tr>
<tr class="odd">
<td>≥ 0.80</td>
<td>Strong</td>
</tr>
<tr class="even">
<td>≥ 0.90</td>
<td>Very strong</td>
</tr>
<tr class="odd">
<td>≥ 0.95</td>
<td>Exceptional</td>
</tr>
</tbody>
</table>
<p>These are conventions, not strict rules — context matters.</p>
</section>
<section id="look-beyond-pp.h4-alone" class="level2" data-number="12.3">
<h2 data-number="12.3" class="anchored" data-anchor-id="look-beyond-pp.h4-alone"><span class="header-section-number">12.3</span> Look Beyond PP.H4 Alone</h2>
<p>Focusing only on PP.H4 is risky: PP.H3 = 0.45 and PP.H4 = 0.50 technically makes H4 the largest single probability, but there’s nearly as much support for “different variants” — the result is genuinely uncertain. A useful diagnostic is the ratio <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPP.H4%7D%20/%20(%5Ctext%7BPP.H3%7D%20+%20%5Ctext%7BPP.H4%7D)">: for PP.H3=0.10, PP.H4=0.90, this gives 0.90 — excellent support for sharing. Low ratios flag ambiguous H3-vs-H4 competition even when PP.H4 looks superficially high.</p>
</section>
<section id="fine-mapping-quality-drives-colocalization-quality" class="level2" data-number="12.4">
<h2 data-number="12.4" class="anchored" data-anchor-id="fine-mapping-quality-drives-colocalization-quality"><span class="header-section-number">12.4</span> Fine-Mapping Quality Drives Colocalization Quality</h2>
<p>A GWAS credible set of 50 SNPs and an eQTL credible set of 60 SNPs create enormous combined uncertainty — colocalization may be inconclusive no matter how it’s run. By contrast, GWAS = {rs39} and eQTL = {rs39} makes colocalization almost trivially easy to interpret (PP.H4 ≈ 1). Poor fine-mapping upstream directly degrades colocalization downstream.</p>
</section>
<section id="four-common-mistakes" class="level2" data-number="12.5">
<h2 data-number="12.5" class="anchored" data-anchor-id="four-common-mistakes"><span class="header-section-number">12.5</span> Four Common Mistakes</h2>
<ol type="1">
<li><strong>Assuming visual overlap = colocalization.</strong> A GWAS peak and an eQTL peak sitting in the same region doesn’t mean “same signal” — strong LD alone can create that appearance. This is exactly why formal colocalization methods exist.</li>
<li><strong>Ignoring LD mismatch.</strong> If the GWAS uses European samples and the eQTL uses African samples, differing LD can yield different credible sets even when the underlying biology is identical. Always consider ancestry.</li>
<li><strong>Treating colocalization as proof of causality.</strong> Even PP.H4 = 0.99 only suggests shared genetic regulation, not that “Gene A causes disease” — that claim needs functional studies, CRISPR experiments, animal models, or perturbation experiments.</li>
<li><strong>Ignoring tissue context.</strong> A brain eQTL colocalization (PP.H4 = 0.95) is far more biologically relevant for schizophrenia than a blood eQTL colocalization (PP.H4 = 0.05) for the same locus — tissue selection matters enormously.</li>
</ol>
</section>
<section id="sensitivity-analysis" class="level2" data-number="12.6">
<h2 data-number="12.6" class="anchored" data-anchor-id="sensitivity-analysis"><span class="header-section-number">12.6</span> Sensitivity Analysis</h2>
<p>Because coloc’s Bayesian priors (<img src="https://latex.codecogs.com/png.latex?p_1">, <img src="https://latex.codecogs.com/png.latex?p_2">, <img src="https://latex.codecogs.com/png.latex?p_%7B12%7D"> — beliefs about how likely a SNP affects trait 1, trait 2, or both) influence the posterior, a good study tests multiple prior settings:</p>
<p><em>Illustrative syntax – <code>dataset1</code>/<code>dataset2</code> are placeholders for your own formatted summary-statistics lists; see the</em> <a href="https://chr1swallace.github.io/coloc/">coloc package documentation</a> <em>for the exact list format each expects.</em></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coloc.abf</span>(dataset1, dataset2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p1 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p2 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p12 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-5</span>)</span></code></pre></div></div>
<p>If PP.H4 = 0.82 under one prior but 0.35 under another, the result is unstable and should be reported cautiously.</p>
</section>
<section id="a-complete-worked-example" class="level2" data-number="12.7">
<h2 data-number="12.7" class="anchored" data-anchor-id="a-complete-worked-example"><span class="header-section-number">12.7</span> A Complete Worked Example</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BDepression%20GWAS%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D"> <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BBrain%20eQTL%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D"> <img src="https://latex.codecogs.com/png.latex?%5Cdownarrow%20%5Ctext%7Bcoloc.susie%7D%20%5Crightarrow%20%5Ctext%7BPP.H4%7D%20=%200.92"></p>
<p>Strong evidence that the same variant influences both gene expression and depression risk — a biologically meaningful hypothesis. A publication should report: gene, tissue, PP.H4, PP.H3, method used, and both credible set sizes — e.g.&nbsp;<em>CACNA1C</em>, prefrontal cortex, <code>coloc.susie</code>, PP.H4 = 0.96, GWAS CS size 2, eQTL CS size 1.</p>
</section>
<section id="hierarchy-of-evidence-and-practical-checklist" class="level2" data-number="12.8">
<h2 data-number="12.8" class="anchored" data-anchor-id="hierarchy-of-evidence-and-practical-checklist"><span class="header-section-number">12.8</span> Hierarchy of Evidence and Practical Checklist</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%20Association%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Association%7D%20%5Crightarrow%20%5Ctext%7BColocalization%7D%20%5Crightarrow%20%5Ctext%7BFunctional%20Validation%7D"></p>
<p>Before trusting a result, check: are both traits genuinely associated (H1/H2/H3/H4)? Is PP.H4 high (preferably &gt;0.8)? Is PP.H3 correspondingly low? Were the credible sets small? Was LD properly ancestry-matched? Is the tissue biologically relevant? Were sensitivity analyses performed across priors?</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Interpret colocalization using the full set of posterior probabilities, not PP.H4 in isolation — a high PP.H4 alongside a non-trivial PP.H3 is genuinely ambiguous. Fine-mapping quality directly limits colocalization quality: poorly resolved credible sets create irreducible uncertainty. Colocalization is strong evidence, not proof, of a shared mechanism — and proper interpretation requires attention to ancestry matching, tissue relevance, and prior sensitivity.</p>
</blockquote>
</section>
</section>
<section id="end-to-end-statistical-genetics-pipeline-from-gwas-to-biological-discovery" class="level1" data-number="13">
<h1 data-number="13"><span class="header-section-number">13</span> End-to-End Statistical Genetics Pipeline — From GWAS to Biological Discovery</h1>
<p>GWAS, fine-mapping, eQTL analysis, and colocalization were each covered individually — but in practice they’re chained into a single integrated pipeline whose goal is to move from <strong>association</strong> to <strong>biological mechanism</strong>.</p>
<section id="the-fundamental-problem" class="level2" data-number="13.1">
<h2 data-number="13.1" class="anchored" data-anchor-id="the-fundamental-problem"><span class="header-section-number">13.1</span> The Fundamental Problem</h2>
<p>A GWAS hit on chromosome 6 for schizophrenia tells us <em>something important is here</em> — but not which variant, which gene, or which mechanism. That gap is what the modern post-GWAS pipeline exists to close.</p>
</section>
<section id="the-complete-workflow" class="level2" data-number="13.2">
<h2 data-number="13.2" class="anchored" data-anchor-id="the-complete-workflow"><span class="header-section-number">13.2</span> The Complete Workflow</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGenotypes%7D%20%5Crightarrow%20%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BSignificant%20Locus%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BCredible%20Sets%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Integration%7D%20%5Crightarrow%20%5Ctext%7BColocalization%7D%20%5Crightarrow%20%5Ctext%7BTarget%20Gene%7D%20%5Crightarrow%20%5Ctext%7BFunctional%20Validation%7D%20%5Crightarrow%20%5Ctext%7BBiological%20Mechanism%7D"></p>
<p>This framework underlies studies from UK Biobank, FinnGen, the Psychiatric Genomics Consortium, GTEx, and PsychENCODE.</p>
<p><strong>Step by step, with a running example (rs39, schizophrenia):</strong></p>
<ol type="1">
<li><strong>GWAS</strong> — 500,000 individuals, 10 million SNPs, model <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPhenotype%7D%20=%20%5Ctext%7BSNP%7D%20+%20%5Ctext%7BCovariates%7D%20+%20%5Ctext%7BError%7D">, output beta/SE/p-value per SNP. rs39 at <img src="https://latex.codecogs.com/png.latex?p=1%5Ctimes10%5E%7B-12%7D"> — strong association, not yet causality. Because of LD, rs39–rs42 may all look significant; GWAS alone can’t say which is causal.</li>
<li><strong>Fine-mapping</strong> — SuSiE/FINEMAP/CARMA/ABF, using GWAS summary stats + LD matrix, narrow this down: rs39, PIP = 0.94, 95% credible set = {rs39, rs40}. What started as ~100 candidate SNPs is now 2 — a dramatic improvement in tractability.</li>
<li><strong>Gene prioritization</strong> — the nearest gene is often <em>not</em> the causal gene, so functional genomics data must be integrated.</li>
<li><strong>eQTL analysis</strong> — rs39 influences <em>CACNA1C</em> expression in brain tissue, giving a testable hypothesis: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7Brs39%7D%20%5Crightarrow%20%5Ctextit%7BCACNA1C%7D%20%5Ctext%7B%20Expression%7D%20%5Crightarrow%20%5Ctext%7BDisease%20Risk%7D">. Fine-mapping answers “which SNP?”; eQTL answers “which gene?”</li>
<li><strong>Fine-mapping the eQTL</strong> — independently fine-map the eQTL signal too: GWAS CS = {rs39}, eQTL CS = {rs39}. Highly suggestive, but still not proof.</li>
<li><strong>Colocalization</strong> — <code>coloc.abf</code> or <code>coloc.susie</code> formally test whether both signals share a causal variant across the five hypotheses (H0: no association; H1: trait 1 only; H2: trait 2 only; H3: different variants; H4: shared variant). PP.H4 = 0.96 → strong evidence for a shared causal variant, often the key result of the whole study.</li>
</ol>
<p><strong>Putting it together:</strong> GWAS finds rs39 → fine-mapping gives PIP = 0.98 → eQTL analysis links rs39 to <em>CACNA1C</em> → colocalization gives PP.H4 = 0.97. This supports <img src="https://latex.codecogs.com/png.latex?%5Ctext%7Brs39%7D%20%5Crightarrow%20%5Ctextit%7BCACNA1C%7D%20%5Ctext%7B%20Expression%7D%20%5Crightarrow%20%5Ctext%7BSchizophrenia%20Risk%7D"> — a biologically meaningful hypothesis distilled from an initial 10 million tested SNPs down to 1 variant, 1 gene, 1 mechanism.</p>
</section>
<section id="real-example-psychiatric-genetics" class="level2" data-number="13.3">
<h2 data-number="13.3" class="anchored" data-anchor-id="real-example-psychiatric-genetics"><span class="header-section-number">13.3</span> Real Example: Psychiatric Genetics</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSchizophrenia%20GWAS%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BBrain%20eQTL%20Data%7D%20%5Crightarrow%20%5Ctext%7BColocalization%7D%20%5Crightarrow%20%5Ctext%7BCandidate%20Gene%7D%20%5Crightarrow%20%5Ctext%7BFunctional%20Validation%7D"></p>
<p>using resources like PsychENCODE, GTEx, and CommonMind.</p>
</section>
<section id="beyond-eqtls-multi-omics-integration" class="level2" data-number="13.4">
<h2 data-number="13.4" class="anchored" data-anchor-id="beyond-eqtls-multi-omics-integration"><span class="header-section-number">13.4</span> Beyond eQTLs: Multi-Omics Integration</h2>
<p>The same fine-mapping + colocalization framework extends to other molecular QTLs: <strong>sQTLs</strong> (splicing), <strong>pQTLs</strong> (protein), <strong>mQTLs</strong> (methylation), <strong>caQTLs</strong> (chromatin accessibility). A modern multi-omics workflow:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Colocalization%7D%20%5Crightarrow%20%5Ctext%7BpQTL%20Colocalization%7D%20%5Crightarrow%20%5Ctext%7BSingle-Cell%20Expression%7D%20%5Crightarrow%20%5Ctext%7BPathway%20Analysis%7D%20%5Crightarrow%20%5Ctext%7BDrug%20Target%20Discovery%7D"></p>
<p><strong>Single-cell data</strong> identifies <em>which cell types</em> express the target gene (e.g.&nbsp;Gene A highly expressed in excitatory neurons but not microglia), adding biological context. <strong>TWAS</strong> (transcriptome-wide association) complements this: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BPredicted%20Expression%7D%20%5Crightarrow%20%5Ctext%7BGene-Level%20Association%7D">. <strong>Mendelian Randomization</strong> goes a step further, testing whether altered expression is <em>causally</em> related to disease (<img src="https://latex.codecogs.com/png.latex?%5Ctext%7BeQTL%7D%20%5Crightarrow%20%5Ctext%7BGene%20Expression%7D%20%5Crightarrow%20%5Ctext%7BDisease%7D">) — stronger evidence than colocalization alone.</p>
</section>
<section id="hierarchy-of-evidence" class="level2" data-number="13.5">
<h2 data-number="13.5" class="anchored" data-anchor-id="hierarchy-of-evidence"><span class="header-section-number">13.5</span> Hierarchy of Evidence</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BFine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BeQTL%20Association%7D%20%5Crightarrow%20%5Ctext%7BColocalization%7D%20%5Crightarrow%20%5Ctext%7BTWAS%7D%20%5Crightarrow%20%5Ctext%7BMendelian%20Randomization%7D%20%5Crightarrow%20%5Ctext%7BFunctional%20Validation%7D"></p>
<p>Each layer adds evidence toward the ultimate chain: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVariant%7D%20%5Crightarrow%20%5Ctext%7BGene%7D%20%5Crightarrow%20%5Ctext%7BCell%20Type%7D%20%5Crightarrow%20%5Ctext%7BPathway%7D%20%5Crightarrow%20%5Ctext%7BDisease%7D">.</p>
<p><strong>Common beginner misconception:</strong> stopping after GWAS. GWAS is usually just the starting point — the real biological discoveries typically emerge during fine-mapping, eQTL integration, colocalization, and functional interpretation. A modern statistical geneticist’s typical project: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%7D%20%5Crightarrow%20%5Ctext%7BSuSiE%20Fine-Mapping%7D%20%5Crightarrow%20%5Ctext%7BGTEx%20eQTL%20Lookup%7D%20%5Crightarrow%20%5Ctext%7Bcoloc.susie%7D%20%5Crightarrow%20%5Ctext%7BTWAS%7D%20%5Crightarrow%20%5Ctext%7BSingle-Cell%20Annotation%7D%20%5Crightarrow%20%5Ctext%7BExperimental%20Validation%7D">.</p>
<blockquote class="blockquote">
<p><strong>Final key takeaways.</strong> The journey from GWAS to biological discovery is a chain of interconnected steps: GWAS identifies associated regions, fine-mapping narrows them to likely causal variants, eQTL analysis links variants to gene expression, and colocalization tests whether the same variant drives both expression and disease risk. Modern statistical genetics increasingly layers in single-cell genomics, TWAS, Mendelian Randomization, and multi-omics data to build a fuller mechanistic picture. The ultimate objective is to move from a significant SNP to a causal gene, a relevant cell type, a biological pathway, and eventually therapeutic insight.</p>
</blockquote>


</section>
</section>

 ]]></description>
  <category>Tutorial</category>
  <category>Genetics</category>
  <category>Fine-Mapping</category>
  <category>GWAS</category>
  <category>Statistical Genetics</category>
  <guid>https://bntechie.github.io/tutorials/Finemapping/Statistical_Fine_Mapping.html</guid>
  <pubDate>Mon, 15 Jun 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/Finemapping/images/fine-mapping.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Mendelian Randomization</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/mendelianR/Mendelian_Randomization.html</link>
  <description><![CDATA[ 




<p>One of the fundamental goals of science is to determine whether one variable causes another.</p>
<p>In medicine, epidemiology, genetics, economics, and social sciences, researchers constantly observe relationships between variables. Observing a relationship, however, is not the same as proving a causal effect.</p>
<p>Consider a few familiar examples:</p>
<ul>
<li>Individuals with a higher body mass index (BMI) tend to have a higher risk of coronary heart disease.</li>
<li>Smokers are more likely to develop lung cancer.</li>
<li>Elevated C-reactive protein (CRP) levels are associated with hypertension.</li>
<li>Individuals who exercise regularly tend to live longer.</li>
</ul>
<p>These observations are informative, but none of them establishes causality on its own.</p>
<p>Understanding the distinction between correlation and causation is one of the most important ideas in statistics and epidemiology. It is also the motivation behind <strong>Mendelian Randomization (MR)</strong>, an approach that uses genetic variants to investigate causal relationships.</p>
<blockquote class="blockquote">
<p><strong>What you’ll learn in this series</strong></p>
<ul>
<li>How to distinguish correlation from causation</li>
<li>Why observational associations can be misleading</li>
<li>What confounding and reverse causation mean</li>
<li>How Mendelian Randomization uses genetic variants as instruments</li>
<li>When MR is a useful tool for causal inference</li>
<li>How to run a complete two-sample MR analysis in R, from instrument selection to sensitivity analysis</li>
</ul>
</blockquote>
<p><strong>Who this is for.</strong> Researchers and students who want an accessible, code-first introduction to Mendelian Randomization with a genetics focus. Familiarity with basic statistics and epidemiology is helpful but not required.</p>
<p><strong>Why MR matters.</strong> Mendelian Randomization helps researchers address causal questions when randomized controlled trials are not feasible. It uses the natural randomization of genetic inheritance to infer whether an exposure may have a causal effect on an outcome.</p>
<section id="part-1-correlation-causation-and-why-we-need-mr" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Part 1 — Correlation, Causation, and Why We Need MR</h1>
<section id="what-is-correlation" class="level2" data-number="1.1">
<h2 data-number="1.1" class="anchored" data-anchor-id="what-is-correlation"><span class="header-section-number">1.1</span> What Is Correlation?</h2>
<p>Correlation describes the extent to which two variables vary together.</p>
<p>When one variable increases and another tends to increase as well, the variables have a <strong>positive correlation</strong>. When one increases while the other decreases, they have a <strong>negative correlation</strong>.</p>
<p>Correlation is most commonly measured with the Pearson correlation coefficient, <img src="https://latex.codecogs.com/png.latex?r">, where <img src="https://latex.codecogs.com/png.latex?-1%20%5Cle%20r%20%5Cle%201">.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Correlation</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><img src="https://latex.codecogs.com/png.latex?r%20=%201"></td>
<td>Perfect positive relationship</td>
</tr>
<tr class="even">
<td><img src="https://latex.codecogs.com/png.latex?r%20=%200"></td>
<td>No linear relationship</td>
</tr>
<tr class="odd">
<td><img src="https://latex.codecogs.com/png.latex?r%20=%20-1"></td>
<td>Perfect negative relationship</td>
</tr>
</tbody>
</table>
<p>Height and weight, for example, are usually positively correlated, since taller individuals generally weigh more than shorter individuals. But a correlation coefficient never tells us whether one variable <em>causes</em> the other.</p>
</section>
<section id="the-central-question" class="level2" data-number="1.2">
<h2 data-number="1.2" class="anchored" data-anchor-id="the-central-question"><span class="header-section-number">1.2</span> The Central Question</h2>
<p>Suppose researchers observe that individuals with elevated CRP levels tend to have higher blood pressure. This raises an obvious question:</p>
<blockquote class="blockquote">
<p>Does CRP cause high blood pressure?</p>
</blockquote>
<p>Several explanations are equally consistent with the data:</p>
<ol type="1">
<li>CRP causes high blood pressure.</li>
<li>High blood pressure causes elevated CRP.</li>
<li>Some other factor influences both CRP and blood pressure.</li>
<li>The relationship is partly causal and partly confounded.</li>
</ol>
<p>Observational data alone cannot distinguish between these possibilities.</p>
</section>
<section id="correlation-does-not-imply-causation" class="level2" data-number="1.3">
<h2 data-number="1.3" class="anchored" data-anchor-id="correlation-does-not-imply-causation"><span class="header-section-number">1.3</span> Correlation Does Not Imply Causation</h2>
<blockquote class="blockquote">
<p>Correlation does not imply causation.</p>
</blockquote>
<p>Two variables can be strongly correlated even when neither directly causes the other. There are two classic reasons this happens: reverse causation and confounding.</p>
<section id="reverse-causation" class="level3" data-number="1.3.1">
<h3 data-number="1.3.1" class="anchored" data-anchor-id="reverse-causation"><span class="header-section-number">1.3.1</span> Reverse Causation</h3>
<p>Reverse causation occurs when the true direction of the relationship is the opposite of what we initially assume. Researchers may observe</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BBiomarker%7D%20%5Crightarrow%20%5Ctext%7BDisease%7D"></p>
<p>and conclude that the biomarker causes disease, when the true relationship runs the other way:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BDisease%7D%20%5Crightarrow%20%5Ctext%7BBiomarker%7D"></p>
<p>Elevated inflammatory markers, for instance, are often observed in people who already have disease — the disease raised the biomarker, not the other way around. Reverse causation is especially problematic in observational studies, because measurements are often taken after disease processes have already begun.</p>
</section>
<section id="confounding" class="level3" data-number="1.3.2">
<h3 data-number="1.3.2" class="anchored" data-anchor-id="confounding"><span class="header-section-number">1.3.2</span> Confounding</h3>
<p>Confounding occurs when a third variable influences both the exposure and the outcome. For example, general health-consciousness influences both exercise habits and diet quality. A researcher might observe a strong association between exercise and diet quality, but the relationship is largely explained by an underlying tendency toward healthy behavior overall, not a direct causal link between the two.</p>
<p><strong>A classic example: ice cream and drowning.</strong> Across a year of data, ice cream sales and drowning incidents both rise in summer and are positively correlated. It would clearly be wrong to conclude</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BIce%20Cream%7D%20%5Crightarrow%20%5Ctext%7BDrowning%7D"></p>
<p>Instead, temperature is the confounder driving both:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BTemperature%7D%20%5Crightarrow%20%5Ctext%7BIce%20Cream%20Sales%7D,%20%5Cqquad%20%5Ctext%7BTemperature%7D%20%5Crightarrow%20%5Ctext%7BDrowning%7D"></p>
<p>This simple example illustrates why associations alone are insufficient for establishing causality.</p>
</section>
</section>
<section id="why-observational-studies-are-challenging" class="level2" data-number="1.4">
<h2 data-number="1.4" class="anchored" data-anchor-id="why-observational-studies-are-challenging"><span class="header-section-number">1.4</span> Why Observational Studies Are Challenging</h2>
<p>Most epidemiological studies are observational: researchers observe naturally occurring variation in exposures such as smoking, alcohol use, obesity, physical activity, diet, and blood biomarkers, without controlling who receives which exposure.</p>
<p>Observational studies are valuable because they are inexpensive and can involve very large populations. But their estimates are frequently affected by confounding, reverse causation, measurement error, and selection bias — so observed associations may not reflect true causal effects.</p>
<section id="the-counterfactual-problem" class="level3" data-number="1.4.1">
<h3 data-number="1.4.1" class="anchored" data-anchor-id="the-counterfactual-problem"><span class="header-section-number">1.4.1</span> The Counterfactual Problem</h3>
<p>A fundamental challenge in causal inference is that we cannot observe alternative realities. For an individual with obesity, we observe their actual outcome,</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BObesity%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"></p>
<p>but we can never simultaneously observe what would have happened to that same person had they not been obese. This unobservable alternative is called the <strong>counterfactual</strong>, and because it can never be directly observed, causal inference is inherently difficult.</p>
</section>
</section>
<section id="randomized-controlled-trials" class="level2" data-number="1.5">
<h2 data-number="1.5" class="anchored" data-anchor-id="randomized-controlled-trials"><span class="header-section-number">1.5</span> Randomized Controlled Trials</h2>
<p>The gold standard for causal inference is the randomized controlled trial (RCT). Participants are randomly assigned to a treatment group or a control group, and randomization balances both measured and unmeasured confounders across the two groups:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BRandomization%7D%20%5Crightarrow%20%5Ctext%7BBalanced%20Confounders%7D%20%5Crightarrow%20%5Ctext%7Bunbiased%20estimate%20of%20Treatment%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"></p>
<p>If the treatment and control groups differ in outcomes after randomization, that difference is more likely to represent a true causal effect.</p>
<section id="why-not-use-rcts-for-everything" class="level3" data-number="1.5.1">
<h3 data-number="1.5.1" class="anchored" data-anchor-id="why-not-use-rcts-for-everything"><span class="header-section-number">1.5.1</span> Why Not Use RCTs for Everything?</h3>
<p>Randomized trials are powerful, but often impossible, unethical, or impractical. We cannot randomly assign people to smoke, to be obese, to drink heavily, or to have high blood pressure. For many important public health questions, randomized experiments simply cannot be performed, so scientists need alternative methods for investigating causality.</p>
</section>
</section>
<section id="natures-randomized-experiment" class="level2" data-number="1.6">
<h2 data-number="1.6" class="anchored" data-anchor-id="natures-randomized-experiment"><span class="header-section-number">1.6</span> Nature’s Randomized Experiment</h2>
<p>Genetics provides a natural form of randomization. During reproduction, genetic variants are transmitted from parents to offspring according to Mendel’s laws, and because this transmission is largely random, genetic variants are generally assigned before birth, before disease onset, before lifestyle choices are made, and before most environmental exposures occur.</p>
<p>This natural randomization creates an opportunity to study causal relationships using genetic information. The central idea is simple:</p>
<blockquote class="blockquote">
<p>If a genetic variant influences an exposure, and that exposure truly causes an outcome, then the genetic variant should also be associated with the outcome.</p>
</blockquote>
<p>This insight is the foundation of Mendelian Randomization.</p>
</section>
<section id="looking-ahead" class="level2" data-number="1.7">
<h2 data-number="1.7" class="anchored" data-anchor-id="looking-ahead"><span class="header-section-number">1.7</span> Looking Ahead</h2>
<p>We saw that observational associations can arise from confounding, reverse causation, or other bias, and why randomized controlled trials are the gold standard for causal inference despite being infeasible for many important questions. The next part introduces Mendelian Randomization itself, and shows how naturally occurring genetic variation can serve as an instrumental variable for investigating causal relationships.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Correlation measures association, not causation.</li>
<li>Observational studies are vulnerable to confounding and reverse causation.</li>
<li>Strong associations do not necessarily indicate causal effects.</li>
<li>Randomized controlled trials reduce bias through randomization, but are not always feasible or ethical.</li>
<li>Genetic variants provide a natural source of randomization that Mendelian Randomization exploits.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-2-what-is-mendelian-randomization" class="level1" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Part 2 — What Is Mendelian Randomization?</h1>
<p>In Part 1 we discussed why establishing causality is difficult, and why RCTs — the gold standard — are not always feasible or ethical. This raises an obvious question:</p>
<blockquote class="blockquote">
<p>Can we obtain evidence about causality without performing a randomized experiment?</p>
</blockquote>
<p>Mendelian Randomization (MR) attempts to answer this question using genetic variation.</p>
<section id="the-central-idea-behind-mendelian-randomization" class="level2" data-number="2.1">
<h2 data-number="2.1" class="anchored" data-anchor-id="the-central-idea-behind-mendelian-randomization"><span class="header-section-number">2.1</span> The Central Idea Behind Mendelian Randomization</h2>
<p>MR uses genetic variants as proxies for modifiable exposures. The key insight is that genetic variants are assigned at conception according to Mendel’s laws of inheritance. Because they are determined before birth, genetic variants cannot be influenced by later disease processes, are generally unaffected by lifestyle choices, and are usually independent of many environmental confounders. This makes them useful instruments for studying causality.</p>
<section id="a-motivating-example" class="level3" data-number="2.1.1">
<h3 data-number="2.1.1" class="anchored" data-anchor-id="a-motivating-example"><span class="header-section-number">2.1.1</span> A Motivating Example</h3>
<p>Suppose researchers observe that individuals with elevated CRP levels tend to have higher blood pressure. Observational data alone cannot tell us whether</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BCRP%7D%20%5Crightarrow%20%5Ctext%7BBlood%20Pressure%7D,%20%5Cqquad%20%5Ctext%7BBlood%20Pressure%7D%20%5Crightarrow%20%5Ctext%7BCRP%7D,%20%5Cqquad%20%5Ctext%7Bor%20both%20are%20driven%20by%20a%20confounder.%7D"></p>
<p>MR attempts to answer this using genetic variants associated with CRP.</p>
</section>
</section>
<section id="mendelian-randomization-as-natures-experiment" class="level2" data-number="2.2">
<h2 data-number="2.2" class="anchored" data-anchor-id="mendelian-randomization-as-natures-experiment"><span class="header-section-number">2.2</span> Mendelian Randomization as Nature’s Experiment</h2>
<p>In an RCT, random assignment of treatment balances confounders:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BRandomization%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"></p>
<p>In Mendelian Randomization, we replace treatment assignment with genetic inheritance. Instead of randomly assigning individuals to a treatment, nature randomly assigns genetic variants during reproduction:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGenetic%20Variant%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"></p>
<p><strong>Example: smoking and lung cancer.</strong> Suppose one genotype is associated with heavier smoking and another with lighter smoking. If smoking truly causes lung cancer, then people carrying the smoking-promoting genotype should also show a higher risk of lung cancer. The genetic variant acts as a proxy for smoking behavior, and comparing groups defined by genotype is less vulnerable to many of the traditional confounders that plague observational comparisons of smokers and non-smokers.</p>
</section>
<section id="what-is-an-instrumental-variable" class="level2" data-number="2.3">
<h2 data-number="2.3" class="anchored" data-anchor-id="what-is-an-instrumental-variable"><span class="header-section-number">2.3</span> What Is an Instrumental Variable?</h2>
<p>An instrumental variable is a variable that helps estimate a causal effect in the presence of confounding. In MR, the genetic variant is the instrument. The exposure might be BMI, smoking, cholesterol, blood pressure, CRP, or alcohol consumption; the outcome might be coronary heart disease, stroke, diabetes, cancer, or depression. The causal framework is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGenetic%20Variant%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"></p>
<p>with the genetic variant influencing the outcome <em>only</em> through the exposure.</p>
<p>The basic MR model has three components:</p>
<ul>
<li><strong>Exposure</strong> — a modifiable factor of interest (BMI, smoking, LDL cholesterol, CRP, physical activity, …)</li>
<li><strong>Outcome</strong> — a disease or trait (coronary heart disease, stroke, type 2 diabetes, Alzheimer’s disease, …)</li>
<li><strong>Instrument</strong> — a genetic variant associated with the exposure (SNPs associated with BMI, cholesterol, smoking behavior, …)</li>
</ul>
</section>
<section id="the-three-core-assumptions-of-mendelian-randomization" class="level2" data-number="2.4">
<h2 data-number="2.4" class="anchored" data-anchor-id="the-three-core-assumptions-of-mendelian-randomization"><span class="header-section-number">2.4</span> The Three Core Assumptions of Mendelian Randomization</h2>
<p>Every MR study depends on three fundamental assumptions. Violating any of them can bias the causal estimate.</p>
<section id="assumption-1-relevance" class="level3" data-number="2.4.1">
<h3 data-number="2.4.1" class="anchored" data-anchor-id="assumption-1-relevance"><span class="header-section-number">2.4.1</span> Assumption 1: Relevance</h3>
<p>The genetic variant must be associated with the exposure:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D"></p>
<p>If a SNP has no relationship with BMI, for example, it cannot tell us anything about whether BMI affects disease. Strong instruments produce more reliable MR estimates; weak instruments can produce unstable, biased results.</p>
</section>
<section id="assumption-2-independence" class="level3" data-number="2.4.2">
<h3 data-number="2.4.2" class="anchored" data-anchor-id="assumption-2-independence"><span class="header-section-number">2.4.2</span> Assumption 2: Independence</h3>
<p>The genetic variant should not be associated with confounding variables such as income, education, diet, exercise, or socioeconomic status:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Cperp%20%5Ctext%7BConfounders%7D"></p>
<p>If the genetic variant is correlated with confounders, it no longer behaves like a randomized experiment.</p>
</section>
<section id="assumption-3-exclusion-restriction" class="level3" data-number="2.4.3">
<h3 data-number="2.4.3" class="anchored" data-anchor-id="assumption-3-exclusion-restriction"><span class="header-section-number">2.4.3</span> Assumption 3: Exclusion Restriction</h3>
<p>The genetic variant must influence the outcome <em>only</em> through the exposure. The desired pathway is</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"></p>
<p>and there should be no direct pathway</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"></p>
<p>that bypasses the exposure. This is usually the hardest assumption to verify.</p>
</section>
</section>
<section id="understanding-pleiotropy" class="level2" data-number="2.5">
<h2 data-number="2.5" class="anchored" data-anchor-id="understanding-pleiotropy"><span class="header-section-number">2.5</span> Understanding Pleiotropy</h2>
<p>A major threat to MR is <strong>pleiotropy</strong> — when a genetic variant influences multiple traits. If a SNP affects both BMI and blood pressure, and we’re studying whether BMI affects blood pressure, the direct SNP → blood pressure effect creates a problem: it violates the exclusion restriction. Later parts in this series discuss methods such as MR-Egger that attempt to detect and correct for pleiotropy.</p>
</section>
<section id="why-genetic-variants-are-useful-instruments" class="level2" data-number="2.6">
<h2 data-number="2.6" class="anchored" data-anchor-id="why-genetic-variants-are-useful-instruments"><span class="header-section-number">2.6</span> Why Genetic Variants Are Useful Instruments</h2>
<p>Genetic variants have three attractive properties:</p>
<ul>
<li><strong>Fixed at conception.</strong> Genotypes are established before birth, and disease cannot alter them, which greatly reduces reverse causation.</li>
<li><strong>Usually precede disease.</strong> This gives a natural temporal ordering: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGenotype%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D">.</li>
<li><strong>Less influenced by lifestyle.</strong> Unlike environmental exposures, genotypes are not modified by diet, exercise, smoking, or medication use, which helps reduce confounding.</li>
</ul>
<p><strong>A conceptual example.</strong> Suppose a SNP is associated with higher CRP levels. Researchers estimate <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BCRP%7D">, then test whether the same SNP is associated with blood pressure. If the SNP influences CRP, the SNP is associated with blood pressure, and the three MR assumptions hold, this provides evidence that CRP may causally influence blood pressure — the central logic of Mendelian Randomization.</p>
</section>
<section id="strengths-and-limitations-of-mendelian-randomization" class="level2" data-number="2.7">
<h2 data-number="2.7" class="anchored" data-anchor-id="strengths-and-limitations-of-mendelian-randomization"><span class="header-section-number">2.7</span> Strengths and Limitations of Mendelian Randomization</h2>
<p>Compared with traditional observational studies, MR offers reduced confounding (genotypes are largely independent of environmental factors), reduced reverse causation (disease cannot change inherited variants), the ability to leverage existing large public GWAS summary statistics, and ethical feasibility for questions that could never be studied with a randomized trial.</p>
<p>MR is not a perfect substitute for an RCT, however. Important challenges include weak instruments, population stratification, horizontal pleiotropy, selection bias, and measurement error. For this reason, MR studies typically perform multiple sensitivity analyses to assess robustness — a theme this series returns to repeatedly.</p>
</section>
<section id="looking-ahead-1" class="level2" data-number="2.8">
<h2 data-number="2.8" class="anchored" data-anchor-id="looking-ahead-1"><span class="header-section-number">2.8</span> Looking Ahead</h2>
<p>Now that we understand the basic MR framework, we’re ready to estimate causal effects. The next part introduces the <strong>Wald Ratio</strong>, the first quantitative MR estimator, based on the relationship between SNP-exposure and SNP-outcome effects.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Mendelian Randomization uses genetic variants as instrumental variables — naturally randomized proxies for exposures.</li>
<li>Every MR study rests on three assumptions: relevance, independence, and exclusion restriction.</li>
<li>Pleiotropy — a variant affecting multiple traits — is a major threat to valid causal inference in MR.</li>
<li>Genetic variants can provide evidence about causal relationships when randomized experiments are impossible.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-3-the-wald-ratio-and-single-snp-mendelian-randomization" class="level1" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> Part 3 — The Wald Ratio and Single-SNP Mendelian Randomization</h1>
<p>In Part 2 we established that a valid MR analysis rests on three assumptions: the genetic variant is associated with the exposure, is independent of confounders, and influences the outcome only through the exposure. Now we can ask a practical question:</p>
<blockquote class="blockquote">
<p>How do we actually estimate a causal effect using a genetic variant?</p>
</blockquote>
<p>The simplest MR estimator is the <strong>Wald Ratio</strong>.</p>
<section id="from-instrumental-variables-to-causal-effects" class="level2" data-number="3.1">
<h2 data-number="3.1" class="anchored" data-anchor-id="from-instrumental-variables-to-causal-effects"><span class="header-section-number">3.1</span> From Instrumental Variables to Causal Effects</h2>
<p>Recall the basic MR framework: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D">. If the SNP influences the exposure, the exposure influences the outcome, and the MR assumptions hold, the SNP should also be associated with the outcome. This gives us two measurable quantities:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D:%20%5Cquad%20%5Cbeta_%7BGX%7D"> <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D:%20%5Cquad%20%5Cbeta_%7BGY%7D"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?G"> is the genetic variant, <img src="https://latex.codecogs.com/png.latex?X"> is the exposure, and <img src="https://latex.codecogs.com/png.latex?Y"> is the outcome. These two quantities are the foundation of the Wald Ratio.</p>
</section>
<section id="the-intuition-behind-the-wald-ratio" class="level2" data-number="3.2">
<h2 data-number="3.2" class="anchored" data-anchor-id="the-intuition-behind-the-wald-ratio"><span class="header-section-number">3.2</span> The Intuition Behind the Wald Ratio</h2>
<p>Imagine a SNP increases BMI by 0.5 units per allele, and the same SNP increases coronary heart disease (CHD) risk by 0.1 units per allele. The natural question is: how much does CHD increase per unit increase in BMI? We estimate this by dividing the SNP-outcome effect by the SNP-exposure effect — exactly what the Wald Ratio does.</p>
</section>
<section id="the-wald-ratio-formula" class="level2" data-number="3.3">
<h2 data-number="3.3" class="anchored" data-anchor-id="the-wald-ratio-formula"><span class="header-section-number">3.3</span> The Wald Ratio Formula</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_%7BMR%7D%20=%20%5Cfrac%7B%5Cbeta_%7BGY%7D%7D%7B%5Cbeta_%7BGX%7D%7D"></p>
<p>This ratio estimates the causal effect of the exposure on the outcome.</p>
<p><strong>Why does it work?</strong> If the true causal effect of <img src="https://latex.codecogs.com/png.latex?X"> on <img src="https://latex.codecogs.com/png.latex?Y"> is <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BXY%7D">, and the SNP affects the outcome only through the exposure, then</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D%20=%20%5Cbeta_%7BGX%7D%5C,%5Cbeta_%7BXY%7D%20%5Cquad%20%5CRightarrow%20%5Cquad%20%5Cbeta_%7BXY%7D%20=%20%5Cfrac%7B%5Cbeta_%7BGY%7D%7D%7B%5Cbeta_%7BGX%7D%7D"></p>
<p>The SNP acts as a naturally randomized perturbation of the exposure, and the resulting change in the outcome carries information about the causal effect.</p>
</section>
<section id="a-numerical-example" class="level2" data-number="3.4">
<h2 data-number="3.4" class="anchored" data-anchor-id="a-numerical-example"><span class="header-section-number">3.4</span> A Numerical Example</h2>
<p>Suppose a GWAS reports <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D%20=%200.20"> for SNP → BMI (each additional effect allele increases BMI by 0.20 units) and <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D%20=%200.08"> for SNP → CHD. The Wald estimate is</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_%7BMR%7D%20=%20%5Cfrac%7B0.08%7D%7B0.20%7D%20=%200.40"></p>
<blockquote class="blockquote">
<p>A one-unit increase in BMI is associated with a 0.40-unit increase in CHD risk, assuming the MR assumptions hold.</p>
</blockquote>
<p>This is the same logic behind the earlier CRP–blood pressure example: an MR estimate built from a genetic instrument can differ substantially from the naive observational association, precisely because it strips out confounding and reverse causation.</p>
</section>
<section id="estimating-uncertainty" class="level2" data-number="3.5">
<h2 data-number="3.5" class="anchored" data-anchor-id="estimating-uncertainty"><span class="header-section-number">3.5</span> Estimating Uncertainty</h2>
<p>Every statistical estimate carries uncertainty, and the Wald Ratio is no exception. Given <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSE%7D(%5Cbeta_%7BGX%7D)"> and <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSE%7D(%5Cbeta_%7BGY%7D)">, the uncertainty in the ratio is commonly approximated with the delta method:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSE%7D(%5Chat%5Cbeta_%7BMR%7D)%20%5Capprox%20%5Cfrac%7B%5Ctext%7BSE%7D(%5Cbeta_%7BGY%7D)%7D%7B%5Cbeta_%7BGX%7D%7D"></p>
<p>More complete versions incorporate uncertainty in both the numerator and denominator; most MR software handles this automatically.</p>
<p>Once we have <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_%7BMR%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSE%7D(%5Chat%5Cbeta_%7BMR%7D)">, a 95% confidence interval follows the usual form:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_%7BMR%7D%20%5Cpm%201.96%20%5Ctimes%20%5Ctext%7BSE%7D(%5Chat%5Cbeta_%7BMR%7D)"></p>
<p>For example, an estimate of <img src="https://latex.codecogs.com/png.latex?0.40"> with a standard error of <img src="https://latex.codecogs.com/png.latex?0.10"> gives a 95% CI of roughly <img src="https://latex.codecogs.com/png.latex?(0.20,%5C%200.60)">. Because zero is not contained in the interval, the estimate is statistically significant at the 5% level.</p>
</section>
<section id="the-importance-of-instrument-strength" class="level2" data-number="3.6">
<h2 data-number="3.6" class="anchored" data-anchor-id="the-importance-of-instrument-strength"><span class="header-section-number">3.6</span> The Importance of Instrument Strength</h2>
<p>The Wald Ratio relies heavily on its denominator, <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D">. If the SNP has only a very weak association with the exposure, the ratio becomes unstable. For example, <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D%20=%200.02"> and <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D%20=%200.001"> gives <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_%7BMR%7D%20=%2020"> — a tiny denominator producing an extreme, unreliable estimate. This is known as the <strong>weak instrument problem</strong>, and using only one SNP typically provides limited statistical power on top of this instability.</p>
</section>
<section id="why-multiple-snps-are-better" class="level2" data-number="3.7">
<h2 data-number="3.7" class="anchored" data-anchor-id="why-multiple-snps-are-better"><span class="header-section-number">3.7</span> Why Multiple SNPs Are Better</h2>
<p>Modern GWAS often identify dozens, hundreds, or even thousands of SNPs associated with a single exposure — 50 for BMI, 100 for cholesterol, 200 for smoking, and so on. Each SNP produces its own Wald Ratio estimate. Rather than relying on any single SNP, we can combine information across many instruments, which increases precision, power, and robustness. The most widely used approach for combining multiple instruments is <strong>Inverse Variance Weighted (IVW) Mendelian Randomization</strong>, covered in Part 4.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>The Wald Ratio is the simplest MR estimator, using a single SNP as an instrumental variable.</li>
<li>The causal estimate is the SNP-outcome effect divided by the SNP-exposure effect.</li>
<li>Strong instruments are essential; weak instruments produce unstable results.</li>
<li>Modern MR studies combine many SNPs using IVW and related approaches rather than relying on one SNP.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-4-multiple-snp-mr-and-the-inverse-variance-weighted-ivw-method" class="level1" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> Part 4 — Multiple-SNP MR and the Inverse Variance Weighted (IVW) Method</h1>
<p>In Part 3 we introduced the Wald Ratio, which uses a single genetic variant as an instrument. Modern MR studies rarely rely on just one SNP — researchers typically use dozens, hundreds, or thousands of variants associated with the exposure. This raises the question:</p>
<blockquote class="blockquote">
<p>How can we combine information from multiple genetic instruments into a single, more precise causal estimate?</p>
</blockquote>
<p>The most widely used answer is the <strong>Inverse Variance Weighted (IVW) Method</strong>.</p>
<section id="why-one-snp-is-usually-not-enough" class="level2" data-number="4.1">
<h2 data-number="4.1" class="anchored" data-anchor-id="why-one-snp-is-usually-not-enough"><span class="header-section-number">4.1</span> Why One SNP Is Usually Not Enough</h2>
<p>A single SNP usually explains only a tiny proportion of variation in the exposure — one BMI-associated SNP might explain less than 0.1% of BMI variance — which limits precision. Any measurement error in the SNP-exposure or SNP-outcome estimate directly affects the causal estimate, and if that one SNP violates an MR assumption, the entire analysis is biased. For these reasons, modern MR studies use many genetic instruments together.</p>
</section>
<section id="combining-multiple-instruments" class="level2" data-number="4.2">
<h2 data-number="4.2" class="anchored" data-anchor-id="combining-multiple-instruments"><span class="header-section-number">4.2</span> Combining Multiple Instruments</h2>
<p>Suppose a GWAS identifies five SNPs associated with BMI:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
</colgroup>
<thead>
<tr class="header">
<th>SNP</th>
<th>SNP → BMI (<img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D">)</th>
<th>SNP → CHD (<img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D">)</th>
<th>Wald Ratio</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>SNP1</td>
<td>0.20</td>
<td>0.08</td>
<td>0.40</td>
</tr>
<tr class="even">
<td>SNP2</td>
<td>0.15</td>
<td>0.06</td>
<td>0.40</td>
</tr>
<tr class="odd">
<td>SNP3</td>
<td>0.10</td>
<td>0.05</td>
<td>0.50</td>
</tr>
<tr class="even">
<td>SNP4</td>
<td>0.25</td>
<td>0.09</td>
<td>0.36</td>
</tr>
<tr class="odd">
<td>SNP5</td>
<td>0.18</td>
<td>0.07</td>
<td>0.39</td>
</tr>
</tbody>
</table>
<p>Now we have five separate estimates of the same causal effect, and the challenge is combining them.</p>
</section>
<section id="why-not-simply-average-them" class="level2" data-number="4.3">
<h2 data-number="4.3" class="anchored" data-anchor-id="why-not-simply-average-them"><span class="header-section-number">4.3</span> Why Not Simply Average Them?</h2>
<p>A simple average treats every SNP equally, but not every SNP is estimated with the same precision. A SNP estimated from a GWAS with a small standard error carries more reliable information than one estimated with a large standard error, so more precise SNPs should contribute more heavily to the combined estimate. This motivates <strong>inverse variance weighting</strong>, a standard meta-analysis technique: more precise estimates receive larger weights, since smaller variance means greater precision:</p>
<p><img src="https://latex.codecogs.com/png.latex?w_i%20=%20%5Cfrac%7B1%7D%7B%5Ctext%7BVar%7D(%5Chat%5Cbeta_i)%7D"></p>
<p><strong>Illustration.</strong> Two SNPs both estimate a causal effect of 0.40, but SNP1 has variance 0.01 (weight <img src="https://latex.codecogs.com/png.latex?w_1%20=%20100">) and SNP2 has variance 0.04 (weight <img src="https://latex.codecogs.com/png.latex?w_2%20=%2025">). SNP1 receives four times more weight because it’s estimated more precisely.</p>
</section>
<section id="the-ivw-formula" class="level2" data-number="4.4">
<h2 data-number="4.4" class="anchored" data-anchor-id="the-ivw-formula"><span class="header-section-number">4.4</span> The IVW Formula</h2>
<p>Given per-SNP Wald Ratio estimates <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_1,%20%5Chat%5Cbeta_2,%20%5Cdots,%20%5Chat%5Cbeta_k"> with weights <img src="https://latex.codecogs.com/png.latex?w_1,%20w_2,%20%5Cdots,%20w_k">, the IVW estimate is a weighted average:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_%7BIVW%7D%20=%20%5Cfrac%7B%5Csum_%7Bi=1%7D%5E%7Bk%7D%20w_i%20%5Chat%5Cbeta_i%7D%7B%5Csum_%7Bi=1%7D%5E%7Bk%7D%20w_i%7D"></p>
<p>The numerator is the weighted sum of SNP-specific causal estimates; the denominator is the total weight. Precise instruments get more influence, noisy ones get less.</p>
<p><strong>A numerical example.</strong> Suppose three SNPs give:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>SNP</th>
<th>Estimate</th>
<th>Variance</th>
<th>Weight</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>SNP1</td>
<td>0.40</td>
<td>0.01</td>
<td>100</td>
</tr>
<tr class="even">
<td>SNP2</td>
<td>0.50</td>
<td>0.02</td>
<td>50</td>
</tr>
<tr class="odd">
<td>SNP3</td>
<td>0.35</td>
<td>0.05</td>
<td>20</td>
</tr>
</tbody>
</table>
<p><img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_%7BIVW%7D%20=%20%5Cfrac%7B100(0.40)%20+%2050(0.50)%20+%2020(0.35)%7D%7B100+50+20%7D%20=%20%5Cfrac%7B72%7D%7B170%7D%20%5Capprox%200.424"></p>
<blockquote class="blockquote">
<p>A one-unit increase in the exposure is associated with a 0.424-unit increase in the outcome, assuming the MR assumptions are satisfied.</p>
</blockquote>
</section>
<section id="an-alternative-view-of-ivw" class="level2" data-number="4.5">
<h2 data-number="4.5" class="anchored" data-anchor-id="an-alternative-view-of-ivw"><span class="header-section-number">4.5</span> An Alternative View of IVW</h2>
<p>IVW can also be understood as a weighted regression of <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D"> on <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D">, weighted by inverse variance, with the slope of that regression equal to the causal estimate. This interpretation becomes useful later when we discuss MR-Egger regression, which is the same regression with the intercept unconstrained.</p>
<p>With a single SNP, <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BIVW%7D%20=%20%5Ctext%7BWald%20Ratio%7D">; with multiple SNPs, <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BIVW%7D"> is a weighted average of Wald Ratios. IVW is therefore a natural extension of the Wald Ratio, not a different estimator.</p>
</section>
<section id="why-ivw-became-the-standard-method" class="level2" data-number="4.6">
<h2 data-number="4.6" class="anchored" data-anchor-id="why-ivw-became-the-standard-method"><span class="header-section-number">4.6</span> Why IVW Became the Standard Method</h2>
<p>IVW became the most widely used MR estimator because it offers higher statistical power (using many SNPs substantially increases power), greater precision (combining information reduces uncertainty), a straightforward causal interpretation, and computational simplicity.</p>
</section>
<section id="the-assumptions-behind-ivw" class="level2" data-number="4.7">
<h2 data-number="4.7" class="anchored" data-anchor-id="the-assumptions-behind-ivw"><span class="header-section-number">4.7</span> The Assumptions Behind IVW</h2>
<p>IVW relies on the same three instrumental variable assumptions from Part 2: relevance (each SNP is associated with the exposure), independence (each SNP is independent of confounders), and exclusion restriction (each SNP affects the outcome only through the exposure, and through no other pathway).</p>
</section>
<section id="the-problem-of-horizontal-pleiotropy" class="level2" data-number="4.8">
<h2 data-number="4.8" class="anchored" data-anchor-id="the-problem-of-horizontal-pleiotropy"><span class="header-section-number">4.8</span> The Problem of Horizontal Pleiotropy</h2>
<p>IVW performs well when every instrument is valid. But if some SNPs affect the outcome through pathways other than the exposure — <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"> directly, alongside <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"> — bias can occur. This is <strong>horizontal pleiotropy</strong>, one of the major threats to Mendelian Randomization, and Part 7 covers it in detail.</p>
</section>
<section id="fixed-effects-and-random-effects-ivw" class="level2" data-number="4.9">
<h2 data-number="4.9" class="anchored" data-anchor-id="fixed-effects-and-random-effects-ivw"><span class="header-section-number">4.9</span> Fixed Effects and Random Effects IVW</h2>
<p>Two versions of IVW are used in practice. <strong>Fixed effects IVW</strong> assumes all SNPs estimate exactly the same causal effect, attributing differences among SNP estimates entirely to sampling variation. <strong>Random effects IVW</strong> allows some additional heterogeneity among SNP estimates, and is often preferred when mild pleiotropy or heterogeneity is suspected.</p>
</section>
<section id="strengths-and-limitations-of-ivw" class="level2" data-number="4.10">
<h2 data-number="4.10" class="anchored" data-anchor-id="strengths-and-limitations-of-ivw"><span class="header-section-number">4.10</span> Strengths and Limitations of IVW</h2>
<p>IVW offers high statistical power, increased precision, use of all available instruments, straightforward interpretation, and wide acceptance in genetic epidemiology. Its limitations are that it is sensitive to pleiotropy, requires valid instruments, can become biased when assumptions are violated, and does not automatically detect directional pleiotropy. Because of these limitations, IVW is usually accompanied by additional sensitivity analyses.</p>
</section>
<section id="looking-ahead-2" class="level2" data-number="4.11">
<h2 data-number="4.11" class="anchored" data-anchor-id="looking-ahead-2"><span class="header-section-number">4.11</span> Looking Ahead</h2>
<p>IVW is often the starting point of an MR analysis, but researchers must still investigate whether its assumptions are reasonable — especially horizontal pleiotropy. Part 5 addresses a related practical question: where do the SNP-exposure and SNP-outcome estimates actually come from? The answer is <strong>Two-Sample Mendelian Randomization</strong>.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Modern MR studies usually use multiple SNPs, each producing a Wald Ratio estimate.</li>
<li>IVW combines these estimates by inverse-variance weighting — more precise instruments get more weight.</li>
<li>IVW can be viewed as a weighted average of Wald Ratios, or as a weighted regression through the origin.</li>
<li>IVW is the standard MR estimator, but is sensitive to horizontal pleiotropy and requires sensitivity analyses.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-5-two-sample-mendelian-randomization" class="level1" data-number="5">
<h1 data-number="5"><span class="header-section-number">5</span> Part 5 — Two-Sample Mendelian Randomization</h1>
<p>In Part 4 we combined multiple genetic instruments using IVW, assuming we already had estimates of <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"> for every variant. This raises an obvious question:</p>
<blockquote class="blockquote">
<p>Where do these estimates actually come from?</p>
</blockquote>
<p>In modern MR studies, they typically come from two separate Genome-Wide Association Studies (GWAS). This approach is called <strong>Two-Sample Mendelian Randomization</strong>, and it is the standard framework for contemporary MR analyses.</p>
<section id="revisiting-the-mr-framework" class="level2" data-number="5.1">
<h2 data-number="5.1" class="anchored" data-anchor-id="revisiting-the-mr-framework"><span class="header-section-number">5.1</span> Revisiting the MR Framework</h2>
<p>To estimate a causal effect we need SNP-exposure and SNP-outcome associations. The natural question is:</p>
<blockquote class="blockquote">
<p>Must these associations come from the same individuals?</p>
</blockquote>
<p>The answer is <strong>no</strong> — and this is one of the major strengths of modern MR.</p>
</section>
<section id="one-sample-mendelian-randomization" class="level2" data-number="5.2">
<h2 data-number="5.2" class="anchored" data-anchor-id="one-sample-mendelian-randomization"><span class="header-section-number">5.2</span> One-Sample Mendelian Randomization</h2>
<p>Historically, MR was performed within a single dataset, measuring genotype, exposure, and outcome in the same individuals:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Person</th>
<th>Genotype</th>
<th>BMI</th>
<th>CHD</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1</td>
<td>AA</td>
<td>24</td>
<td>No</td>
</tr>
<tr class="even">
<td>2</td>
<td>AG</td>
<td>28</td>
<td>Yes</td>
</tr>
<tr class="odd">
<td>3</td>
<td>GG</td>
<td>31</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p>This is <strong>one-sample MR</strong>. Its advantages are complete data on all variables in the same individuals, flexible modeling with access to individual-level data, and the ability to adjust directly for covariates. Its limitations are the expense of collecting genotype, exposure, and outcome data on the same individuals, the resulting small sample sizes and limited power compared to large GWAS consortia, and restricted access to individual-level genetic data. These limitations motivated <strong>two-sample MR</strong>.</p>
</section>
<section id="two-sample-mendelian-randomization" class="level2" data-number="5.3">
<h2 data-number="5.3" class="anchored" data-anchor-id="two-sample-mendelian-randomization"><span class="header-section-number">5.3</span> Two-Sample Mendelian Randomization</h2>
<p>Two-sample MR uses summary statistics from two separate GWAS: an exposure GWAS provides <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D"> associations, and an outcome GWAS provides <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"> associations. The participants in the two studies do not need to overlap.</p>
<p><strong>Exposure GWAS example (BMI):</strong></p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>SNP</th>
<th>Beta (<img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D">)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>rs1</td>
<td>0.12</td>
</tr>
<tr class="even">
<td>rs2</td>
<td>0.08</td>
</tr>
<tr class="odd">
<td>rs3</td>
<td>0.15</td>
</tr>
</tbody>
</table>
<p><strong>Outcome GWAS example (same SNPs, a disease outcome):</strong></p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>SNP</th>
<th>Beta (<img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D">)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>rs1</td>
<td>0.05</td>
</tr>
<tr class="even">
<td>rs2</td>
<td>0.03</td>
</tr>
<tr class="odd">
<td>rs3</td>
<td>0.06</td>
</tr>
</tbody>
</table>
<p>Researchers no longer need individual-level genotype, exposure, and outcome data in the same participants — publicly available GWAS summary statistics can simply be combined, which dramatically increases statistical power. Thousands of GWAS summary statistic datasets are now available through resources such as UK Biobank, FinnGen, the GIANT Consortium, CARDIoGRAMplusC4D, and the Psychiatric Genomics Consortium.</p>
<p><strong>A practical example.</strong> To study <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BBMI%7D%20%5Crightarrow%20%5Ctext%7BCHD%7D">, we might use a BMI GWAS with <img src="https://latex.codecogs.com/png.latex?N%20=%20700%7B,%7D000"> and a CHD GWAS with <img src="https://latex.codecogs.com/png.latex?N%20=%20200%7B,%7D000">; the participants don’t need to overlap, and we simply extract SNP associations from both.</p>
</section>
<section id="the-assumption-of-population-similarity" class="level2" data-number="5.4">
<h2 data-number="5.4" class="anchored" data-anchor-id="the-assumption-of-population-similarity"><span class="header-section-number">5.4</span> The Assumption of Population Similarity</h2>
<p>Although the two samples need not contain the same individuals, they should ideally represent similar populations. A European-ancestry exposure GWAS paired with a European-ancestry outcome GWAS is fine; pairing a European-ancestry exposure GWAS with an East Asian-ancestry outcome GWAS is potentially problematic, since ancestry differences can affect SNP effects and introduce bias.</p>
</section>
<section id="sample-overlap" class="level2" data-number="5.5">
<h2 data-number="5.5" class="anchored" data-anchor-id="sample-overlap"><span class="header-section-number">5.5</span> Sample Overlap</h2>
<p>Can the same individuals appear in both GWAS? Yes — but excessive overlap can sometimes create bias. <strong>No overlap</strong> (fully independent participant sets) is the ideal situation. <strong>Partial overlap</strong>, common in modern biobanks, is often acceptable, especially with strong instruments. <strong>Complete overlap</strong> makes the analysis behave more like one-sample MR, and bias can become more problematic when instruments are weak.</p>
<p>An important property of two-sample MR is that weak instrument bias behaves differently than in one-sample MR: in one-sample MR, weak instruments tend to bias estimates toward the observational association, while in two-sample MR they generally bias estimates toward the null — a property that makes two-sample MR particularly attractive.</p>
</section>
<section id="why-summary-statistics-are-sufficient" class="level2" data-number="5.6">
<h2 data-number="5.6" class="anchored" data-anchor-id="why-summary-statistics-are-sufficient"><span class="header-section-number">5.6</span> Why Summary Statistics Are Sufficient</h2>
<p>One of the most remarkable features of two-sample MR is that individual-level data are not required — for each SNP we only need an effect size, standard error, effect allele, and other allele, all of which are routinely reported in GWAS summary statistics. This is why so many MR studies can now be conducted with freely available public data.</p>
</section>
<section id="the-typical-two-sample-mr-workflow" class="level2" data-number="5.7">
<h2 data-number="5.7" class="anchored" data-anchor-id="the-typical-two-sample-mr-workflow"><span class="header-section-number">5.7</span> The Typical Two-Sample MR Workflow</h2>
<ol type="1">
<li>Select genetic instruments from the exposure GWAS.</li>
<li>Extract SNP-outcome associations from the outcome GWAS.</li>
<li>Harmonize alleles between the two datasets.</li>
<li>Calculate SNP-specific Wald Ratios.</li>
<li>Combine estimates using IVW.</li>
<li>Perform sensitivity analyses.</li>
</ol>
</section>
<section id="strengths-and-limitations-of-two-sample-mr" class="level2" data-number="5.8">
<h2 data-number="5.8" class="anchored" data-anchor-id="strengths-and-limitations-of-two-sample-mr"><span class="header-section-number">5.8</span> Strengths and Limitations of Two-Sample MR</h2>
<p>Its strengths are access to extremely large sample sizes, publicly available data, increased statistical power, and broad applicability across thousands of exposure–outcome pairs. Its limitations include the need for population similarity between the two GWAS, the risk of sample overlap bias, the practical challenge of harmonization (Part 6), and the fact that pleiotropy can still violate MR assumptions regardless of sample structure.</p>
</section>
<section id="looking-ahead-3" class="level2" data-number="5.9">
<h2 data-number="5.9" class="anchored" data-anchor-id="looking-ahead-3"><span class="header-section-number">5.9</span> Looking Ahead</h2>
<p>Before SNP associations from two different studies can be combined, we must verify that effect alleles, reference alleles, strand orientation, and palindromic SNPs are all correctly aligned. This process — <strong>harmonization</strong> — is one of the most important practical steps in MR, and is the subject of Part 6.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Two-sample MR uses separate GWAS for the exposure and the outcome; participants need not overlap.</li>
<li>Modern MR relies primarily on publicly available summary statistics, enabling very large sample sizes.</li>
<li>Exposure and outcome GWAS should ideally come from similar populations; excessive sample overlap can introduce bias.</li>
<li>Two-sample MR has become the standard framework for contemporary MR studies.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-6-harmonization-of-exposure-and-outcome-data" class="level1" data-number="6">
<h1 data-number="6"><span class="header-section-number">6</span> Part 6 — Harmonization of Exposure and Outcome Data</h1>
<p>In Part 5 we saw that two-sample MR combines information from separate exposure and outcome GWAS. To estimate a causal effect we need SNP-exposure and SNP-outcome effects for the same genetic variants — but before those effects can be combined, we must ensure they refer to the same allele. This process is called <strong>harmonization</strong>.</p>
<p>Harmonization looks like a simple data-cleaning step, but it is one of the most important stages of an MR analysis: a mistake here can completely reverse the interpretation of a causal effect.</p>
<section id="why-harmonization-is-necessary" class="level2" data-number="6.1">
<h2 data-number="6.1" class="anchored" data-anchor-id="why-harmonization-is-necessary"><span class="header-section-number">6.1</span> Why Harmonization Is Necessary</h2>
<p>Recall the Wald Ratio, <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta%20=%20%5Cbeta_%7BGY%7D/%5Cbeta_%7BGX%7D">. This calculation assumes both effect estimates refer to exactly the same allele. If they don’t, the causal estimate is wrong.</p>
<p>Every SNP has two alleles — for example rs123 might be A/G, rs456 might be C/T. One allele is designated the <strong>effect allele</strong> (the allele the GWAS effect size is reported for); the other is the <strong>non-effect</strong> or <strong>other</strong> allele. If a GWAS reports SNP rs123 with effect allele A and beta 0.10, that means each additional copy of A increases the trait by 0.10 units.</p>
<section id="why-allele-alignment-matters" class="level3" data-number="6.1.1">
<h3 data-number="6.1.1" class="anchored" data-anchor-id="why-allele-alignment-matters"><span class="header-section-number">6.1.1</span> Why Allele Alignment Matters</h3>
<p>Suppose the exposure GWAS reports rs123 with effect allele A and beta 0.10, while the outcome GWAS reports the same SNP with effect allele G and beta <img src="https://latex.codecogs.com/png.latex?-0.05">. At first glance these look like different effects — but the two studies are simply using different reference alleles. The outcome estimate must be converted so both studies refer to the same allele before we can compute a Wald Ratio.</p>
<p><strong>Correct harmonization.</strong> Exposure GWAS: EA = A, OA = G, beta = 0.10. Outcome GWAS: EA = G, OA = A, beta = <img src="https://latex.codecogs.com/png.latex?-0.05">. Since the exposure effect allele (A) is the outcome’s <em>other</em> allele, we flip the sign of the outcome beta and align to A: outcome becomes EA = A, beta = <img src="https://latex.codecogs.com/png.latex?+0.05">. Now both datasets refer to allele A.</p>
<p><strong>What happens if we skip this step?</strong> If we naively divide <img src="https://latex.codecogs.com/png.latex?-0.05"> by <img src="https://latex.codecogs.com/png.latex?0.10">, we get <img src="https://latex.codecogs.com/png.latex?-0.50"> — a <em>negative</em> causal effect. After correct harmonization, the ratio becomes <img src="https://latex.codecogs.com/png.latex?+0.50">. A simple allele mismatch can completely reverse the biological interpretation of a study.</p>
</section>
</section>
<section id="dna-strand-orientation" class="level2" data-number="6.2">
<h2 data-number="6.2" class="anchored" data-anchor-id="dna-strand-orientation"><span class="header-section-number">6.2</span> DNA Strand Orientation</h2>
<p>DNA has two complementary strands, with pairing rules A–T and C–G, so a SNP can be reported on either strand. A/G on the forward strand is T/C on the reverse strand — both represent the same underlying variant, which creates an additional harmonization challenge. If one GWAS reports rs123 as A/G and another reports it as T/C, these may be the same SNP viewed from opposite strands, and harmonization software must account for this.</p>
<p><strong>Strand flipping</strong> resolves this by translating alleles: A↔︎T and C↔︎G, ensuring exposure and outcome datasets refer to the same biological allele.</p>
</section>
<section id="palindromic-snps" class="level2" data-number="6.3">
<h2 data-number="6.3" class="anchored" data-anchor-id="palindromic-snps"><span class="header-section-number">6.3</span> Palindromic SNPs</h2>
<p>Some SNPs create a special challenge: those with allele pairs A/T or C/G are called <strong>palindromic</strong>, because flipping the strand of A/T gives T/A — which looks identical from the opposite direction. This creates ambiguity: given an exposure GWAS reporting EA = A, OA = T and an outcome GWAS reporting EA = T, OA = A for the same palindromic SNP, we cannot immediately tell whether the alleles are correctly aligned.</p>
<p><strong>Using allele frequencies to resolve ambiguity.</strong> If the exposure GWAS reports an effect allele frequency (EAF) of 0.10 and the outcome GWAS reports 0.11, the similar frequencies suggest the same allele is being referenced. If instead the frequencies were 0.10 versus 0.90, that would indicate a strand mismatch. Many MR software packages use allele frequency comparisons like this during harmonization — though when EAF is close to 0.50, orientation cannot be inferred reliably, and these ambiguous palindromic SNPs are usually removed from the analysis.</p>
</section>
<section id="harmonization-workflow" class="level2" data-number="6.4">
<h2 data-number="6.4" class="anchored" data-anchor-id="harmonization-workflow"><span class="header-section-number">6.4</span> Harmonization Workflow</h2>
<p>A typical harmonization procedure follows five steps:</p>
<ol type="1">
<li><strong>Match SNP identifiers</strong> — confirm the same rsID exists in both datasets.</li>
<li><strong>Compare effect alleles</strong> — determine whether exposure and outcome datasets use the same allele.</li>
<li><strong>Flip effect sizes if necessary</strong> — reverse the sign of beta when alleles differ.</li>
<li><strong>Check strand orientation</strong> — resolve forward/reverse strand differences.</li>
<li><strong>Remove ambiguous SNPs</strong> — exclude palindromic SNPs that can’t be confidently aligned.</li>
</ol>
</section>
<section id="harmonization-in-twosamplemr" class="level2" data-number="6.5">
<h2 data-number="6.5" class="anchored" data-anchor-id="harmonization-in-twosamplemr"><span class="header-section-number">6.5</span> Harmonization in TwoSampleMR</h2>
<p>The <code>TwoSampleMR</code> package automates this entire process:</p>
<div id="eee4f355-2ac5-45c4-9ff7-0124c44f6c45" class="cell" data-execution_count="1">
<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;">Sys.getenv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OPENGWAS_JWT"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
'eyJhbGciOiJSUzI1NiIsImtpZCI6ImFwaS1qd3QiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhcGkub3Blbmd3YXMuaW8iLCJhdWQiOiJhcGkub3Blbmd3YXMuaW8iLCJzdWIiOiJuaXZlZGl0YS5ob21lQGdtYWlsLmNvbSIsImlhdCI6MTc4NTA5NTYzMCwiZXhwIjoxNzg2MzA1MjMwfQ.ncPxT99pTGyra1p3Yv0cc-vQgRaIBT7lGI2F2LbSdKdXNnZYNZEy0L-EzM8fMtkVy_zg_CqnJ4wYWhbD-kSGtq8GtlnDh7RxJTy5DOWo3dhOBn6gM4WuyWy87Mc_k8vlLAPcO1UCimsiv2St7lN5d1I1vyQfOm8c2Oq2oZp3P0C6tQG6smD5CdcH8i31OyLbIl-15cuLYvzaGXMdUbPDWodv4Rx8urYjsoFGVWbIF-MNilg4g4-y7wmd7I4bIzObAp_KFT0ty1w0I9-YKhcSJH2ERCOcxDfEJgtNa8R9txCrRee4rNldJo2STE0UCpnVE3O84R34pgil5ImORmYp6w'
</div>
</div>
<div id="95cc12e4-7ed2-422e-956d-fb8cc09c9e42" class="cell" data-execution_count="2">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#install.packages("remotes")</span></span>
<span id="cb2-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#remotes::install_github("MRCIEU/TwoSampleMR")</span></span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(TwoSampleMR)</span>
<span id="cb2-4"></span>
<span id="cb2-5">exposure_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extract_instruments</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outcomes =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ieu-a-2"</span>)</span>
<span id="cb2-6"></span>
<span id="cb2-7">outcome_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extract_outcome_data</span>(</span>
<span id="cb2-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">snps =</span> exposure_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>SNP,</span>
<span id="cb2-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outcomes =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ieu-a-7"</span></span>
<span id="cb2-10">)</span>
<span id="cb2-11"></span>
<span id="cb2-12">harmonised_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">harmonise_data</span>(</span>
<span id="cb2-13">  exposure_dat,</span>
<span id="cb2-14">  outcome_dat</span>
<span id="cb2-15">)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>TwoSampleMR version 0.7.9 


 [&gt;] New authentication requirements: https://mrcieu.github.io/ieugwasr/articles/guide.html#authentication.

 [&gt;] Major upgrades to our servers completed to improve service and stability.

 [&gt;] We need your help to shape our emerging roadmap!

     Please take 2 minutes to give us feedback -

     https://forms.office.com/e/eSr7EFAfCG

Extracting data for 78 SNP(s) from 1 GWAS(s)

Querying id chunk 1 of 1

Querying variant chunk 1 of 2

Querying variant chunk 2 of 2

Harmonising Body mass index || id:ieu-a-2 (ieu-a-2) and Coronary heart disease || id:ieu-a-7 (ieu-a-7)

Removing the following SNPs for being palindromic with intermediate allele frequencies:
rs1558902
</code></pre>
</div>
</div>
<p>This function aligns alleles, flips effect sizes, resolves strand issues, and removes problematic SNPs.</p>
<p><strong>Example workflow:</strong></p>
<div id="65a4f806" class="cell" data-execution_count="3">
<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">exposure_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extract_instruments</span>(</span>
<span id="cb4-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outcomes =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ieu-a-2"</span></span>
<span id="cb4-3">)</span>
<span id="cb4-4"></span>
<span id="cb4-5">outcome_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extract_outcome_data</span>(</span>
<span id="cb4-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">snps =</span> exposure_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>SNP,</span>
<span id="cb4-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outcomes =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ieu-a-7"</span></span>
<span id="cb4-8">)</span>
<span id="cb4-9"></span>
<span id="cb4-10">harmonised_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">harmonise_data</span>(</span>
<span id="cb4-11">  exposure_dat,</span>
<span id="cb4-12">  outcome_dat</span>
<span id="cb4-13">)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>Extracting data for 78 SNP(s) from 1 GWAS(s)

Querying id chunk 1 of 1

Querying variant chunk 1 of 2

Querying variant chunk 2 of 2

Harmonising Body mass index || id:ieu-a-2 (ieu-a-2) and Coronary heart disease || id:ieu-a-7 (ieu-a-7)

Removing the following SNPs for being palindromic with intermediate allele frequencies:
rs1558902
</code></pre>
</div>
</div>
<p>After harmonization, effect alleles match, beta estimates are aligned, and Wald Ratios can be calculated safely.</p>
</section>
<section id="common-harmonization-errors" class="level2" data-number="6.6">
<h2 data-number="6.6" class="anchored" data-anchor-id="common-harmonization-errors"><span class="header-section-number">6.6</span> Common Harmonization Errors</h2>
<p>Several mistakes recur in MR studies: <strong>allele mismatch</strong> (exposure and outcome effects referring to different alleles), <strong>strand mismatch</strong> (forward and reverse strands not aligned), <strong>incorrect SNP matching</strong> (the wrong variants merged together), and <strong>ignoring palindromic SNPs</strong> (retaining ambiguous SNPs that should have been excluded). Any of these can produce incorrect causal estimates.</p>
<p>After harmonization, it’s good practice to inspect the number of SNPs retained versus removed, allele frequencies, strand flips performed, and palindromic SNP exclusions — unexpected patterns here often signal problems in the input data.</p>
</section>
<section id="why-harmonization-is-so-important" class="level2" data-number="6.7">
<h2 data-number="6.7" class="anchored" data-anchor-id="why-harmonization-is-so-important"><span class="header-section-number">6.7</span> Why Harmonization Is So Important</h2>
<p>The statistical methods used in MR can be sophisticated, but even the most advanced estimator cannot correct for incorrectly aligned alleles. A perfectly implemented IVW analysis run on improperly harmonized data will still produce misleading results.</p>
<blockquote class="blockquote">
<p>Harmonization is not a minor preprocessing step. It is a critical component of Mendelian Randomization.</p>
</blockquote>
</section>
<section id="looking-ahead-4" class="level2" data-number="6.8">
<h2 data-number="6.8" class="anchored" data-anchor-id="looking-ahead-4"><span class="header-section-number">6.8</span> Looking Ahead</h2>
<p>Now that exposure and outcome datasets are aligned, we can examine one of the most important threats to MR: <strong>horizontal pleiotropy</strong>, which occurs when genetic variants influence the outcome through pathways other than the exposure, violating MR’s core assumptions.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Harmonization ensures exposure and outcome effect estimates refer to the same allele before combining them.</li>
<li>Getting harmonization wrong can silently reverse the sign of a causal estimate.</li>
<li>Strand orientation and palindromic SNPs are the two trickiest sources of ambiguity.</li>
<li><code>harmonise_data()</code> in <code>TwoSampleMR</code> automates allele alignment, strand resolution, and exclusion of unresolvable SNPs.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-7-horizontal-pleiotropy" class="level1" data-number="7">
<h1 data-number="7"><span class="header-section-number">7</span> Part 7 — Horizontal Pleiotropy</h1>
<p>Now that exposure and outcome datasets can be correctly aligned (Part 6), we turn to one of the biggest threats to Mendelian Randomization: <strong>horizontal pleiotropy</strong>.</p>
<p>In genetics, pleiotropy — a single variant influencing more than one phenotype — is extremely common. A single SNP might influence BMI, type 2 diabetes, blood pressure, and cholesterol simultaneously, by affecting appetite, insulin resistance, and physical activity all at once. Pleiotropy is normal biology; the real question is whether it violates MR’s assumptions.</p>
<section id="revisiting-the-mr-framework-1" class="level2" data-number="7.1">
<h2 data-number="7.1" class="anchored" data-anchor-id="revisiting-the-mr-framework-1"><span class="header-section-number">7.1</span> Revisiting the MR Framework</h2>
<p>The ideal MR model is <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"> — for example, <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BBMI%7D%20%5Crightarrow%20%5Ctext%7BCHD%7D">, with no alternative pathways. Under these conditions, MR can validly estimate a causal effect.</p>
<p>The <strong>exclusion restriction assumption</strong> states that the genetic variant influences the outcome only through the exposure:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D%20%5Cquad%20%5Ctext%7B(allowed)%7D"> <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D%20%5C%20%5Ctext%7Bvia%20any%20other%20pathway%7D%20%5Cquad%20%5Ctext%7B(not%20allowed)%7D"></p>
<p>This is exactly where pleiotropy becomes important.</p>
</section>
<section id="two-types-of-pleiotropy" class="level2" data-number="7.2">
<h2 data-number="7.2" class="anchored" data-anchor-id="two-types-of-pleiotropy"><span class="header-section-number">7.2</span> Two Types of Pleiotropy</h2>
<section id="vertical-pleiotropy" class="level3" data-number="7.2.1">
<h3 data-number="7.2.1" class="anchored" data-anchor-id="vertical-pleiotropy"><span class="header-section-number">7.2.1</span> Vertical Pleiotropy</h3>
<p>Vertical pleiotropy occurs when a SNP affects downstream traits <em>through</em> the exposure — for example, <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BLDL%20Cholesterol%7D%20%5Crightarrow%20%5Ctext%7BAtherosclerosis%7D%20%5Crightarrow%20%5Ctext%7BCHD%7D">. The SNP affects CHD through a biological chain of events mediated entirely by the exposure pathway, so this does <strong>not</strong> violate the exclusion restriction. This is exactly the type of causal pathway MR is designed to capture, and vertical pleiotropy is generally not considered a problem for MR.</p>
</section>
<section id="horizontal-pleiotropy" class="level3" data-number="7.2.2">
<h3 data-number="7.2.2" class="anchored" data-anchor-id="horizontal-pleiotropy"><span class="header-section-number">7.2.2</span> Horizontal Pleiotropy</h3>
<p>Horizontal pleiotropy occurs when a SNP influences the outcome through a pathway <em>other than</em> the exposure. For example, if <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BBMI%7D"> and, simultaneously, <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BBlood%20Pressure%7D"> directly, and we’re studying <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BBMI%7D%20%5Crightarrow%20%5Ctext%7BBlood%20Pressure%7D">, the direct SNP effect creates an alternative pathway that violates the exclusion restriction.</p>
<p>The outcome is now influenced by two routes — through the exposure, and through an independent pleiotropic pathway — making it impossible to determine how much of the SNP-outcome association is truly mediated by the exposure. The observed SNP-outcome effect becomes:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BObserved%20Effect%7D%20=%20%5Ctext%7BCausal%20Effect%20(via%20exposure)%7D%20+%20%5Ctext%7BPleiotropic%20Effect%20(direct)%7D"></p>
<p><strong>A numerical example.</strong> Suppose <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D%20=%200.20"> (SNP → BMI) and the true causal effect <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BXY%7D%20=%200.30"> (BMI → CHD), so the expected SNP-outcome effect via the exposure alone is <img src="https://latex.codecogs.com/png.latex?0.20%20%5Ctimes%200.30%20=%200.06">. Now suppose the SNP also directly affects CHD with a pleiotropic effect of <img src="https://latex.codecogs.com/png.latex?0.04">. The observed SNP-outcome effect becomes <img src="https://latex.codecogs.com/png.latex?0.06%20+%200.04%20=%200.10">, and the Wald Ratio is <img src="https://latex.codecogs.com/png.latex?0.10%20/%200.20%20=%200.50"> — far from the true causal effect of <img src="https://latex.codecogs.com/png.latex?0.30">, purely because of horizontal pleiotropy.</p>
</section>
</section>
<section id="balanced-vs.-directional-pleiotropy" class="level2" data-number="7.3">
<h2 data-number="7.3" class="anchored" data-anchor-id="balanced-vs.-directional-pleiotropy"><span class="header-section-number">7.3</span> Balanced vs.&nbsp;Directional Pleiotropy</h2>
<p><strong>Balanced pleiotropy</strong> occurs when some SNPs have positive pleiotropic effects and others have negative ones that roughly cancel out — e.g.&nbsp;<img src="https://latex.codecogs.com/png.latex?+0.03,%20-0.04,%20+0.01,%20-0.02"> averaging to approximately zero. In this case, IVW estimates may remain relatively unbiased.</p>
<p><strong>Directional pleiotropy</strong> occurs when pleiotropic effects consistently point in the same direction — e.g.&nbsp;<img src="https://latex.codecogs.com/png.latex?+0.03,%20+0.04,%20+0.02,%20+0.05">, averaging to a clearly positive value. This systematically biases the MR estimate and is much more problematic than balanced pleiotropy.</p>
<p>A <strong>valid instrument</strong> satisfies all MR assumptions (<img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"> only); an <strong>invalid instrument</strong> violates at least one, most commonly through horizontal pleiotropy.</p>
</section>
<section id="why-pleiotropy-is-so-common" class="level2" data-number="7.4">
<h2 data-number="7.4" class="anchored" data-anchor-id="why-pleiotropy-is-so-common"><span class="header-section-number">7.4</span> Why Pleiotropy Is So Common</h2>
<p>Modern GWAS have repeatedly shown that many genetic variants influence multiple traits simultaneously — obesity, diabetes, blood pressure, and lipids, for instance, often share genetic architecture. This widespread genetic sharing is sometimes called <strong>biological pleiotropy</strong>, and as a result:</p>
<blockquote class="blockquote">
<p>Pleiotropy should generally be expected rather than considered unusual.</p>
</blockquote>
</section>
<section id="detecting-pleiotropy" class="level2" data-number="7.5">
<h2 data-number="7.5" class="anchored" data-anchor-id="detecting-pleiotropy"><span class="header-section-number">7.5</span> Detecting Pleiotropy</h2>
<p>Pleiotropy cannot always be observed directly, but several statistical methods attempt to detect it: MR-Egger regression, Cochran’s Q test, MR-PRESSO, leave-one-out analysis, weighted median estimation, and weighted mode estimation. These methods form the basis of MR sensitivity analyses, covered in the following parts.</p>
<p><strong>Heterogeneity as a warning sign.</strong> If multiple SNPs are all valid instruments, they should estimate approximately the same causal effect — e.g.&nbsp;Wald Ratios of 0.32, 0.29, 0.34, 0.31 across four SNPs are highly consistent. But if one SNP produces a wildly different estimate (say 1.80 among otherwise consistent 0.3-ish values), that may indicate horizontal pleiotropy, a data problem, or an invalid instrument. Large heterogeneity often motivates further investigation.</p>
</section>
<section id="why-we-need-robust-mr-methods" class="level2" data-number="7.6">
<h2 data-number="7.6" class="anchored" data-anchor-id="why-we-need-robust-mr-methods"><span class="header-section-number">7.6</span> Why We Need Robust MR Methods</h2>
<p>IVW assumes every instrument is valid. In reality, some SNPs may be pleiotropic, invalid, or violate MR assumptions outright. Researchers therefore developed robust methods that remain informative even when some instruments are invalid — <strong>MR-Egger</strong>, <strong>weighted median</strong>, and <strong>weighted mode</strong> — each making different assumptions about the nature of the pleiotropy present. These are the subjects of Parts 8–10.</p>
</section>
<section id="the-big-picture" class="level2" data-number="7.7">
<h2 data-number="7.7" class="anchored" data-anchor-id="the-big-picture"><span class="header-section-number">7.7</span> The Big Picture</h2>
<p>Pleiotropy is not merely a technical nuisance — it is one of the central challenges in causal inference using genetics. The modern MR toolkit exists largely because some degree of pleiotropy is almost inevitable. The goal is not necessarily to eliminate pleiotropy, but to detect it, quantify it, and assess whether it meaningfully changes the causal conclusions.</p>
</section>
<section id="looking-ahead-5" class="level2" data-number="7.8">
<h2 data-number="7.8" class="anchored" data-anchor-id="looking-ahead-5"><span class="header-section-number">7.8</span> Looking Ahead</h2>
<p>The most famous method for addressing horizontal pleiotropy is <strong>MR-Egger regression</strong>, which extends the IVW framework to allow for directional pleiotropy and provides a statistical test for pleiotropic bias. That’s the subject of Part 8.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Pleiotropy occurs when a genetic variant influences multiple traits.</li>
<li>Vertical pleiotropy generally does not violate MR assumptions; horizontal pleiotropy does.</li>
<li>Balanced pleiotropy is usually less problematic than directional pleiotropy.</li>
<li>Detecting pleiotropy — rather than assuming it away — is a central goal of MR sensitivity analysis.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-8-mr-egger-regression-detecting-and-adjusting-for-directional-pleiotropy" class="level1" data-number="8">
<h1 data-number="8"><span class="header-section-number">8</span> Part 8 — MR-Egger Regression: Detecting and Adjusting for Directional Pleiotropy</h1>
<p>Part 7 established that horizontal pleiotropy is one of the biggest threats to Mendelian Randomization. IVW assumes every genetic instrument is valid, but if some SNPs influence the outcome through pathways other than the exposure, the IVW estimate can become biased. This raises a natural question:</p>
<blockquote class="blockquote">
<p>Can we detect whether pleiotropy is affecting our MR analysis?</p>
</blockquote>
<p><strong>MR-Egger regression</strong> was developed to answer this. Unlike IVW, MR-Egger allows genetic variants to have direct effects on the outcome, and provides a statistical framework for detecting directional pleiotropy.</p>
<section id="why-ivw-can-fail" class="level2" data-number="8.1">
<h2 data-number="8.1" class="anchored" data-anchor-id="why-ivw-can-fail"><span class="header-section-number">8.1</span> Why IVW Can Fail</h2>
<p>IVW essentially fits a weighted regression <em>through the origin</em>:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D%20=%20%5Cbeta_%7BMR%7D%5C,%5Cbeta_%7BGX%7D%20+%20%5Cepsilon"></p>
<p>The intercept is fixed at zero, which means IVW assumes there is no average pleiotropic effect across SNPs. If this is violated, the causal estimate may be biased.</p>
</section>
<section id="the-idea-behind-mr-egger" class="level2" data-number="8.2">
<h2 data-number="8.2" class="anchored" data-anchor-id="the-idea-behind-mr-egger"><span class="header-section-number">8.2</span> The Idea Behind MR-Egger</h2>
<p>MR-Egger extends the IVW regression by allowing a non-zero intercept:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D%20=%20%5Calpha%20+%20%5Cbeta_%7BMR%7D%5C,%5Cbeta_%7BGX%7D%20+%20%5Cepsilon"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?%5Calpha"> is the intercept, <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BMR%7D"> is the causal estimate, and <img src="https://latex.codecogs.com/png.latex?%5Cepsilon"> is random error. The intercept term is the key innovation.</p>
</section>
<section id="why-the-intercept-matters" class="level2" data-number="8.3">
<h2 data-number="8.3" class="anchored" data-anchor-id="why-the-intercept-matters"><span class="header-section-number">8.3</span> Why the Intercept Matters</h2>
<p>The intercept represents the <em>average pleiotropic effect</em> across all instruments. If <img src="https://latex.codecogs.com/png.latex?%5Calpha%20=%200">, there is no evidence of directional pleiotropy; if <img src="https://latex.codecogs.com/png.latex?%5Calpha%20%5Cne%200">, there is evidence that SNPs are affecting the outcome through pathways other than the exposure. The intercept becomes a diagnostic tool for pleiotropy itself.</p>
<p><strong>Visualizing IVW vs.&nbsp;MR-Egger.</strong> Plotting <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D"> on the x-axis and <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D"> on the y-axis, each SNP becomes a point. IVW forces the regression line through the origin <img src="https://latex.codecogs.com/png.latex?(0,0)">; MR-Egger allows the line to cross the y-axis at <img src="https://latex.codecogs.com/png.latex?%5Calpha">, giving it the flexibility to account for directional pleiotropy.</p>
</section>
<section id="slope-and-intercept" class="level2" data-number="8.4">
<h2 data-number="8.4" class="anchored" data-anchor-id="slope-and-intercept"><span class="header-section-number">8.4</span> Slope and Intercept</h2>
<p>The slope of the MR-Egger regression, <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BMR%7D">, is interpreted just like the IVW estimate — for example, <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BMR%7D%20=%200.40"> suggests a one-unit increase in the exposure causes a 0.40-unit increase in the outcome, assuming the MR-Egger assumptions hold.</p>
<p>The intercept is often more interesting than the slope. Suppose <img src="https://latex.codecogs.com/png.latex?%5Calpha%20=%200.03">: this suggests that, on average, SNPs have positive direct effects on the outcome not mediated through the exposure — evidence for directional pleiotropy. Researchers formally test <img src="https://latex.codecogs.com/png.latex?H_0:%20%5Calpha%20=%200"> against <img src="https://latex.codecogs.com/png.latex?H_A:%20%5Calpha%20%5Cne%200">; a significant result suggests pleiotropic bias.</p>
<p>Recall from Part 7 that under <strong>balanced pleiotropy</strong> the average pleiotropic effect is approximately zero, so the MR-Egger intercept should also be approximately zero. Under <strong>directional pleiotropy</strong>, the average effect is non-zero, and the intercept should be significantly different from zero — exactly what MR-Egger is designed to detect.</p>
</section>
<section id="the-inside-assumption" class="level2" data-number="8.5">
<h2 data-number="8.5" class="anchored" data-anchor-id="the-inside-assumption"><span class="header-section-number">8.5</span> The InSIDE Assumption</h2>
<p>MR-Egger introduces a new assumption: <strong>Instrument Strength Independent of Direct Effect</strong>, or <strong>InSIDE</strong>. It states:</p>
<blockquote class="blockquote">
<p>The strength of the SNP-exposure association is independent of the direct pleiotropic effect.</p>
</blockquote>
<p>In other words, strong instruments should not systematically have larger pleiotropic effects than weak instruments — mathematically, direct effects and instrument strengths should be uncorrelated.</p>
<p>This matters because the MR-Egger slope can remain unbiased even when <em>every</em> SNP is pleiotropic — but only if InSIDE holds. If InSIDE is violated, both the intercept and the slope may become misleading, and unfortunately InSIDE usually cannot be tested directly.</p>
</section>
<section id="comparing-ivw-and-mr-egger" class="level2" data-number="8.6">
<h2 data-number="8.6" class="anchored" data-anchor-id="comparing-ivw-and-mr-egger"><span class="header-section-number">8.6</span> Comparing IVW and MR-Egger</h2>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Feature</th>
<th>IVW</th>
<th>MR-Egger</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Allows non-zero intercept</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>Detects directional pleiotropy</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="odd">
<td>Higher statistical power</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr class="even">
<td>More robust to pleiotropy</td>
<td>No</td>
<td>Yes</td>
</tr>
</tbody>
</table>
</section>
<section id="when-should-mr-egger-be-used" class="level2" data-number="8.7">
<h2 data-number="8.7" class="anchored" data-anchor-id="when-should-mr-egger-be-used"><span class="header-section-number">8.7</span> When Should MR-Egger Be Used?</h2>
<p>MR-Egger is particularly useful when many instruments are available, pleiotropy is suspected, or researchers want a dedicated sensitivity analysis for the IVW assumptions. It has become one of the standard robustness checks in modern MR.</p>
</section>
<section id="strengths-and-limitations-of-mr-egger" class="level2" data-number="8.8">
<h2 data-number="8.8" class="anchored" data-anchor-id="strengths-and-limitations-of-mr-egger"><span class="header-section-number">8.8</span> Strengths and Limitations of MR-Egger</h2>
<p>Its strengths are that the intercept test provides direct evidence of pleiotropic bias, it can remain informative even when all SNPs are somewhat pleiotropic, and it’s one of the most widely used sensitivity analyses in MR. Its limitations are lower statistical power (wider confidence intervals than IVW), heavy dependence on the untestable InSIDE assumption, sensitivity to a small number of outlying SNPs, and a general requirement for a large number of instruments to perform well.</p>
</section>
<section id="why-mr-egger-is-usually-a-sensitivity-analysis" class="level2" data-number="8.9">
<h2 data-number="8.9" class="anchored" data-anchor-id="why-mr-egger-is-usually-a-sensitivity-analysis"><span class="header-section-number">8.9</span> Why MR-Egger Is Usually a Sensitivity Analysis</h2>
<p>Most MR studies report IVW, MR-Egger, weighted median, and weighted mode side by side, then compare results. If all methods point in the same direction, confidence in the causal conclusion increases; if they disagree substantially, further investigation is warranted.</p>
</section>
<section id="the-big-picture-1" class="level2" data-number="8.10">
<h2 data-number="8.10" class="anchored" data-anchor-id="the-big-picture-1"><span class="header-section-number">8.10</span> The Big Picture</h2>
<p>MR-Egger exists because researchers recognized that pleiotropy is widespread in genetics. Rather than assuming it away, MR-Egger attempts to detect and adjust for it — one of the most important methodological developments in modern MR.</p>
</section>
<section id="looking-ahead-6" class="level2" data-number="8.11">
<h2 data-number="8.11" class="anchored" data-anchor-id="looking-ahead-6"><span class="header-section-number">8.11</span> Looking Ahead</h2>
<p>Although robust to some forms of pleiotropy, MR-Egger often has low statistical power. Part 9 introduces the <strong>weighted median estimator</strong>, which can provide consistent causal estimates even when up to half of the instruments are invalid.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>MR-Egger extends IVW by allowing a non-zero intercept.</li>
<li>The intercept tests for directional pleiotropy; the slope estimates the causal effect.</li>
<li>A significant intercept suggests pleiotropic bias in the IVW estimate.</li>
<li>MR-Egger relies on the untestable InSIDE assumption and typically has lower power than IVW.</li>
<li>It is normally used as a sensitivity analysis rather than a primary estimator.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-9-weighted-median-mendelian-randomization" class="level1" data-number="9">
<h1 data-number="9"><span class="header-section-number">9</span> Part 9 — Weighted Median Mendelian Randomization</h1>
<p>Part 8 introduced MR-Egger, a method that can detect and partially account for directional pleiotropy. MR-Egger was an important advance, but it has real limitations: lower statistical power, wider confidence intervals, dependence on the untestable InSIDE assumption, and sensitivity to outlying SNPs.</p>
<p>Researchers therefore sought a method that stays robust when some genetic instruments are invalid, while retaining reasonable statistical power. The <strong>weighted median estimator</strong> is one of the most successful answers, and has become one of the most widely used sensitivity analyses in MR.</p>
<section id="why-do-we-need-another-method" class="level2" data-number="9.1">
<h2 data-number="9.1" class="anchored" data-anchor-id="why-do-we-need-another-method"><span class="header-section-number">9.1</span> Why Do We Need Another Method?</h2>
<p>IVW performs well when all instruments are valid, but suppose we have 100 SNPs and 10, 20, or 30 of them are invalid. IVW can become biased, because <em>every</em> SNP contributes to the final estimate — even a relatively small number of problematic instruments can distort the result. Researchers wanted a method that could tolerate some invalid instruments.</p>
</section>
<section id="the-core-idea" class="level2" data-number="9.2">
<h2 data-number="9.2" class="anchored" data-anchor-id="the-core-idea"><span class="header-section-number">9.2</span> The Core Idea</h2>
<p>The weighted median estimator rests on a simple observation:</p>
<blockquote class="blockquote">
<p>If most instruments are valid, the middle estimate should still be reliable.</p>
</blockquote>
<p>Rather than averaging SNP estimates, the weighted median focuses on the center of the distribution, which makes it much less sensitive to extreme values and invalid instruments.</p>
<p><strong>Revisiting Wald Ratios.</strong> Suppose five SNPs give estimates of 0.30, 0.35, 0.40, 0.42, and 2.50. The last value is dramatically larger than the rest — possibly due to horizontal pleiotropy, data errors, a weak instrument, or a genuinely invalid instrument. IVW will be pulled toward this outlier; the weighted median is far less affected.</p>
</section>
<section id="what-is-a-median" class="level2" data-number="9.3">
<h2 data-number="9.3" class="anchored" data-anchor-id="what-is-a-median"><span class="header-section-number">9.3</span> What Is a Median?</h2>
<p>A median is the middle value in an ordered list. For <img src="https://latex.codecogs.com/png.latex?%5C%7B1,%202,%203,%204,%205%5C%7D"> the median is <img src="https://latex.codecogs.com/png.latex?3">. Unlike a mean, the median resists extreme values: for <img src="https://latex.codecogs.com/png.latex?%5C%7B1,%202,%203,%204,%20100%5C%7D"> the mean is <img src="https://latex.codecogs.com/png.latex?22">, but the median is still <img src="https://latex.codecogs.com/png.latex?3">.</p>
<p>In MR, we don’t simply take the plain median of SNP estimates — each SNP has a different level of precision, and more precise SNPs should contribute more information. So we use a <strong>weighted median</strong>: the estimate where 50% of the total weight lies on either side.</p>
<p><strong>A simple example.</strong></p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>SNP</th>
<th>Estimate</th>
<th>Weight</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>SNP1</td>
<td>0.20</td>
<td>10</td>
</tr>
<tr class="even">
<td>SNP2</td>
<td>0.25</td>
<td>20</td>
</tr>
<tr class="odd">
<td>SNP3</td>
<td>0.30</td>
<td>30</td>
</tr>
<tr class="even">
<td>SNP4</td>
<td>0.35</td>
<td>25</td>
</tr>
<tr class="odd">
<td>SNP5</td>
<td>1.50</td>
<td>15</td>
</tr>
</tbody>
</table>
<p>Total weight is 100; the weighted median corresponds to the point where cumulative weight reaches 50. SNP5 has an extreme estimate, but because it carries only 15% of the total weight, it has limited influence on the final result.</p>
</section>
<section id="the-50-rule" class="level2" data-number="9.4">
<h2 data-number="9.4" class="anchored" data-anchor-id="the-50-rule"><span class="header-section-number">9.4</span> The 50% Rule</h2>
<p>The weighted median estimator has a remarkable property: it produces a consistent causal estimate provided that</p>
<blockquote class="blockquote">
<p>More than 50% of the total weight comes from valid instruments.</p>
</blockquote>
<p>This is often called the <strong>50% valid instrument assumption</strong>. Even if 40% of SNP weight comes from invalid instruments and 60% from valid ones, the weighted median can still recover the correct causal effect — substantially more robust than IVW, which is biased by <em>any</em> invalid instrument contributing to the average.</p>
<p><strong>Comparing IVW and weighted median.</strong> Suppose 90 SNPs estimate 0.30 and 10 pleiotropic SNPs estimate 2.00. IVW will be pulled upward because all SNPs contribute to the average, but the weighted median remains close to 0.30, provided the majority of weight comes from valid instruments.</p>
</section>
<section id="comparing-ivw-mr-egger-and-weighted-median" class="level2" data-number="9.5">
<h2 data-number="9.5" class="anchored" data-anchor-id="comparing-ivw-mr-egger-and-weighted-median"><span class="header-section-number">9.5</span> Comparing IVW, MR-Egger, and Weighted Median</h2>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Feature</th>
<th>IVW</th>
<th>MR-Egger</th>
<th>Weighted Median</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>All instruments valid</td>
<td>Required</td>
<td>Not required</td>
<td>Not required</td>
</tr>
<tr class="even">
<td>Detects pleiotropy</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr class="odd">
<td>Robust to invalid SNPs</td>
<td>Limited</td>
<td>Moderate</td>
<td>Strong</td>
</tr>
<tr class="even">
<td>Statistical power</td>
<td>High</td>
<td>Low</td>
<td>Moderate</td>
</tr>
</tbody>
</table>
<p><strong>Scenario 1.</strong> IVW = 0.52, MR-Egger = 0.40, Weighted Median = 0.42: IVW is noticeably larger while MR-Egger and the weighted median agree — suggestive of some pleiotropic bias in IVW.</p>
<p><strong>Scenario 2.</strong> IVW = 0.45, MR-Egger = 0.44, Weighted Median = 0.43: all methods agree closely, providing little evidence of major pleiotropic bias and strong support for the causal effect.</p>
<p>The weighted median is particularly useful when a small number of SNPs produce extreme estimates — for instance, four SNPs clustered around 0.30 alongside one SNP at 5.00. IVW would be pulled toward that outlier; the weighted median stays close to 0.30.</p>
</section>
<section id="when-does-weighted-median-fail" class="level2" data-number="9.6">
<h2 data-number="9.6" class="anchored" data-anchor-id="when-does-weighted-median-fail"><span class="header-section-number">9.6</span> When Does Weighted Median Fail?</h2>
<p>It’s not perfect. Problems occur when more than 50% of the weight comes from invalid instruments, when most SNPs share similar pleiotropic effects, or when strong directional pleiotropy affects the majority of instruments. In these cases, the weighted median can also become biased.</p>
</section>
<section id="why-weighted-median-became-popular" class="level2" data-number="9.7">
<h2 data-number="9.7" class="anchored" data-anchor-id="why-weighted-median-became-popular"><span class="header-section-number">9.7</span> Why Weighted Median Became Popular</h2>
<p>The weighted median occupies an attractive middle ground: more robust than IVW, and more precise with greater statistical power than MR-Egger. As a result, it’s now routinely included in MR sensitivity analyses. A typical MR study might report IVW = 0.48, MR-Egger = 0.39, Weighted Median = 0.41; researchers examine the direction, magnitude, and confidence intervals of each, and consistency across methods strengthens confidence in causal conclusions.</p>
</section>
<section id="looking-ahead-7" class="level2" data-number="9.8">
<h2 data-number="9.8" class="anchored" data-anchor-id="looking-ahead-7"><span class="header-section-number">9.8</span> Looking Ahead</h2>
<p>The weighted median still assumes that more than 50% of instrument weight is valid. Part 10 introduces the <strong>weighted mode estimator</strong>, which takes a different perspective entirely:</p>
<blockquote class="blockquote">
<p>The largest cluster of SNP estimates is most likely to represent the true causal effect.</p>
</blockquote>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>The weighted median is a robust MR method based on the median, weighted by precision, of SNP-specific causal estimates.</li>
<li>It remains consistent if more than 50% of the total weight comes from valid instruments.</li>
<li>It is less sensitive to outliers than IVW, and generally has more power than MR-Egger.</li>
<li>It cannot directly detect pleiotropy, and is typically reported alongside IVW and MR-Egger as a sensitivity analysis.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-10-weighted-mode-mendelian-randomization" class="level1" data-number="10">
<h1 data-number="10"><span class="header-section-number">10</span> Part 10 — Weighted Mode Mendelian Randomization</h1>
<p>Part 9 introduced the weighted median estimator, robust as long as more than 50% of total instrument weight comes from valid SNPs. Researchers asked a natural follow-up question:</p>
<blockquote class="blockquote">
<p>What if fewer than 50% of the instruments are valid?</p>
</blockquote>
<p>In some situations the majority of SNPs may not be valid instruments, yet a cluster of SNPs may still identify the true causal effect. This idea motivated <strong>mode-based Mendelian Randomization</strong>, commonly known as the <strong>weighted mode estimator</strong>.</p>
<section id="why-another-robust-method" class="level2" data-number="10.1">
<h2 data-number="10.1" class="anchored" data-anchor-id="why-another-robust-method"><span class="header-section-number">10.1</span> Why Another Robust Method?</h2>
<p>Recall the assumptions behind the methods so far: IVW requires all instruments to be valid; MR-Egger allows pleiotropy but relies on InSIDE; weighted median requires more than 50% of total weight to be valid. But what if only 30% or 40% of SNPs are valid — what if valid instruments simply don’t form a majority? Can we still recover the correct causal effect? The weighted mode estimator attempts to answer yes.</p>
</section>
<section id="the-core-idea-1" class="level2" data-number="10.2">
<h2 data-number="10.2" class="anchored" data-anchor-id="the-core-idea-1"><span class="header-section-number">10.2</span> The Core Idea</h2>
<p>The weighted mode estimator rests on a simple intuition:</p>
<blockquote class="blockquote">
<p>Valid instruments should estimate approximately the same causal effect.</p>
</blockquote>
<p>If multiple SNPs are valid, their Wald Ratio estimates should cluster around the true causal effect; invalid instruments may scatter in many different directions. Therefore:</p>
<blockquote class="blockquote">
<p>The largest cluster of SNP estimates is likely to represent the true causal effect.</p>
</blockquote>
<p>This cluster defines the <strong>mode</strong>.</p>
</section>
<section id="what-is-a-mode" class="level2" data-number="10.3">
<h2 data-number="10.3" class="anchored" data-anchor-id="what-is-a-mode"><span class="header-section-number">10.3</span> What Is a Mode?</h2>
<p>In statistics, the mode is the most frequently occurring value — for <img src="https://latex.codecogs.com/png.latex?%5C%7B1,%202,%202,%202,%203,%204%5C%7D"> the mode is <img src="https://latex.codecogs.com/png.latex?2">, since it appears most often. The weighted mode estimator extends this idea to clusters of MR estimates rather than single repeated values.</p>
<p><strong>From Wald Ratios to clusters.</strong> Suppose SNP-specific estimates are 0.30, 0.31, 0.29, 0.32, 1.50, 1.40, and <img src="https://latex.codecogs.com/png.latex?-0.60">. Three distinct clusters emerge: Cluster A = <img src="https://latex.codecogs.com/png.latex?%5C%7B0.29,%200.30,%200.31,%200.32%5C%7D">, Cluster B = <img src="https://latex.codecogs.com/png.latex?%5C%7B1.40,%201.50%5C%7D">, Cluster C = <img src="https://latex.codecogs.com/png.latex?%5C%7B-0.60%5C%7D">. The largest cluster is A, so the weighted mode estimate is approximately <img src="https://latex.codecogs.com/png.latex?0.30">.</p>
</section>
<section id="the-plurality-valid-assumption" class="level2" data-number="10.4">
<h2 data-number="10.4" class="anchored" data-anchor-id="the-plurality-valid-assumption"><span class="header-section-number">10.4</span> The Plurality-Valid Assumption</h2>
<p>Weighted median requires that more than 50% of total weight come from valid instruments. Weighted mode requires only that the <em>largest cluster</em> of SNPs consist of valid instruments — the <strong>plurality-valid assumption</strong>.</p>
<p><strong>Majority vs.&nbsp;plurality.</strong> A <em>majority</em> means more than 50% — e.g.&nbsp;60% valid SNPs versus 40% invalid. A <em>plurality</em> means the largest group, but not necessarily more than 50% — e.g.&nbsp;40% valid SNPs, 35% “invalid type A,” and 25% “invalid type B.” Here valid instruments don’t form a majority, but they do form the largest cluster, and the weighted mode estimator can still work.</p>
<p>This is powerful: the weighted mode can succeed in situations where both IVW and weighted median fail, because it requires only the largest cluster to be valid — a much weaker and often more realistic assumption.</p>
</section>
<section id="comparing-the-four-main-mr-estimators" class="level2" data-number="10.5">
<h2 data-number="10.5" class="anchored" data-anchor-id="comparing-the-four-main-mr-estimators"><span class="header-section-number">10.5</span> Comparing the Four Main MR Estimators</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 20%">
<col style="width: 20%">
<col style="width: 20%">
<col style="width: 20%">
<col style="width: 20%">
</colgroup>
<thead>
<tr class="header">
<th>Feature</th>
<th>IVW</th>
<th>MR-Egger</th>
<th>Weighted Median</th>
<th>Weighted Mode</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Requires all SNPs valid</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr class="even">
<td>Detects pleiotropy</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr class="odd">
<td>Robust to invalid instruments</td>
<td>Limited</td>
<td>Moderate</td>
<td>Strong</td>
<td>Strong</td>
</tr>
<tr class="even">
<td>Statistical power</td>
<td>High</td>
<td>Lower</td>
<td>Moderate</td>
<td>Moderate</td>
</tr>
<tr class="odd">
<td>Key assumption</td>
<td>All valid</td>
<td>InSIDE</td>
<td>&gt;50% valid weight</td>
<td>Largest cluster valid</td>
</tr>
</tbody>
</table>
<p><strong>Example.</strong> IVW = 0.55, MR-Egger = 0.38, Weighted Median = 0.41, Weighted Mode = 0.40: IVW is noticeably larger while the three robust methods agree closely — a pattern that may indicate pleiotropic bias affecting IVW. When all four methods agree closely instead, that provides strong support for a stable causal estimate.</p>
</section>
<section id="why-weighted-mode-is-useful-and-its-limitations" class="level2" data-number="10.6">
<h2 data-number="10.6" class="anchored" data-anchor-id="why-weighted-mode-is-useful-and-its-limitations"><span class="header-section-number">10.6</span> Why Weighted Mode Is Useful — and Its Limitations</h2>
<p>Weighted mode tolerates invalid instruments, doesn’t require the InSIDE assumption, and doesn’t require a majority of valid SNPs — it can remain informative when other methods struggle. Its limitations: results are sensitive to how clusters are identified, it typically has lower precision (larger standard errors) than IVW, it is less familiar to many researchers than IVW or MR-Egger, and it performs poorly if SNP estimates form a broad continuous distribution rather than clear clusters.</p>
</section>
<section id="why-weighted-mode-is-usually-a-sensitivity-analysis" class="level2" data-number="10.7">
<h2 data-number="10.7" class="anchored" data-anchor-id="why-weighted-mode-is-usually-a-sensitivity-analysis"><span class="header-section-number">10.7</span> Why Weighted Mode Is Usually a Sensitivity Analysis</h2>
<p>As with MR-Egger and weighted median, most studies report weighted mode alongside IVW, MR-Egger, and weighted median rather than as a standalone primary analysis. Agreement across all four increases confidence that an observed causal effect is not being driven by violations of MR assumptions.</p>
</section>
<section id="the-robust-mr-toolbox" class="level2" data-number="10.8">
<h2 data-number="10.8" class="anchored" data-anchor-id="the-robust-mr-toolbox"><span class="header-section-number">10.8</span> The Robust MR Toolbox</h2>
<p>At this point we have four major estimators: <strong>IVW</strong> (primary analysis), <strong>MR-Egger</strong> (detects directional pleiotropy), <strong>weighted median</strong> (robust if &gt;50% of weight is valid), and <strong>weighted mode</strong> (robust if the largest cluster is valid). Together these form the foundation of modern MR sensitivity analysis.</p>
<blockquote class="blockquote">
<p>Even when some instruments are invalid, the true causal signal often emerges as the dominant pattern among the valid instruments.</p>
</blockquote>
</section>
<section id="looking-ahead-8" class="level2" data-number="10.9">
<h2 data-number="10.9" class="anchored" data-anchor-id="looking-ahead-8"><span class="header-section-number">10.9</span> Looking Ahead</h2>
<p>Having covered the four most widely used MR estimators, Part 11 turns to how researchers combine them systematically to evaluate the robustness of a causal conclusion — including Cochran’s Q statistic, heterogeneity testing, and leave-one-out analysis.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>The weighted mode estimator identifies the largest cluster of SNP-specific causal estimates.</li>
<li>It relies on the plurality-valid assumption, weaker than the weighted median’s 50% rule.</li>
<li>It does not require the InSIDE assumption and can remain consistent even when fewer than 50% of instruments are valid.</li>
<li>It is one of the most robust MR estimators, typically used alongside IVW, MR-Egger, and weighted median.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-11-sensitivity-analyses-in-mendelian-randomization" class="level1" data-number="11">
<h1 data-number="11"><span class="header-section-number">11</span> Part 11 — Sensitivity Analyses in Mendelian Randomization</h1>
<p>Parts 4 through 10 introduced four major MR estimators: IVW, MR-Egger, weighted median, and weighted mode. Each attempts to estimate the causal effect of an exposure on an outcome, but each relies on different assumptions. This raises the obvious question:</p>
<blockquote class="blockquote">
<p>Which estimate should we trust?</p>
</blockquote>
<p>In practice, MR rarely relies on a single estimator. Instead, researchers run a battery of <strong>sensitivity analyses</strong> to evaluate whether their conclusions are robust to violations of MR’s assumptions — among the most important components of a modern MR study.</p>
<section id="why-sensitivity-analyses-are-necessary" class="level2" data-number="11.1">
<h2 data-number="11.1" class="anchored" data-anchor-id="why-sensitivity-analyses-are-necessary"><span class="header-section-number">11.1</span> Why Sensitivity Analyses Are Necessary</h2>
<p>Recall the three core MR assumptions: relevance, independence, and exclusion restriction. Unfortunately, we cannot directly verify all of them — some SNPs may be invalid instruments, horizontal pleiotropy may be present, and measurement errors may occur. As a result:</p>
<blockquote class="blockquote">
<p>A single MR estimate is rarely sufficient.</p>
</blockquote>
<p>Sensitivity analyses help determine whether conclusions remain stable under different assumptions. The goal is not necessarily to <em>prove</em> that an estimate is correct, but to ask: how sensitive is the result to potential violations of MR assumptions? If multiple methods agree, confidence increases; if they disagree substantially, caution is warranted.</p>
</section>
<section id="the-four-core-mr-estimators-side-by-side" class="level2" data-number="11.2">
<h2 data-number="11.2" class="anchored" data-anchor-id="the-four-core-mr-estimators-side-by-side"><span class="header-section-number">11.2</span> The Four Core MR Estimators, Side by Side</h2>
<p>Most MR studies report all four: <strong>IVW</strong> as the primary analysis, <strong>MR-Egger</strong> to test for directional pleiotropy, <strong>weighted median</strong> as robust when more than 50% of weight is valid, and <strong>weighted mode</strong> as robust when the largest cluster of SNPs is valid. Together they provide complementary perspectives on the causal effect.</p>
<p><strong>Scenario 1 — strong agreement.</strong> IVW = 0.42, MR-Egger = 0.40, Weighted Median = 0.43, Weighted Mode = 0.41. All methods point the same direction with similar effect sizes — little evidence of major violations, strengthening confidence in the conclusion.</p>
<p><strong>Scenario 2 — moderate differences.</strong> IVW = 0.48, MR-Egger = 0.39, Weighted Median = 0.42, Weighted Mode = 0.40. Estimates differ somewhat but direction is consistent — possible mild pleiotropy; the causal conclusion may still be reasonable, but with greater uncertainty.</p>
<p><strong>Scenario 3 — strong disagreement.</strong> IVW = 0.70, MR-Egger = 0.10, Weighted Median = 0.15, Weighted Mode = 0.12. Large disagreement suggests a strong possibility of pleiotropic bias and likely violation of IVW’s assumptions — researchers should investigate further before making causal claims.</p>
</section>
<section id="heterogeneity-in-mendelian-randomization" class="level2" data-number="11.3">
<h2 data-number="11.3" class="anchored" data-anchor-id="heterogeneity-in-mendelian-randomization"><span class="header-section-number">11.3</span> Heterogeneity in Mendelian Randomization</h2>
<p>If every SNP is a valid instrument, each should estimate approximately the same causal effect — e.g.&nbsp;0.31, 0.29, 0.33, 0.30 across four SNPs. If instead estimates differ dramatically — 0.31, 0.29, 1.75, <img src="https://latex.codecogs.com/png.latex?-0.50"> — this variability is called <strong>heterogeneity</strong>, and it may indicate horizontal pleiotropy, invalid instruments, data quality problems, population differences, or outlying SNPs. Heterogeneity is an important warning signal.</p>
<section id="cochrans-q-statistic" class="level3" data-number="11.3.1">
<h3 data-number="11.3.1" class="anchored" data-anchor-id="cochrans-q-statistic"><span class="header-section-number">11.3.1</span> Cochran’s Q Statistic</h3>
<p>The most common heterogeneity test in MR is <strong>Cochran’s Q</strong>, which asks: do SNP-specific causal estimates vary more than expected by chance? The null hypothesis is that all SNPs estimate the same causal effect; the alternative is that at least some differ.</p>
<p>A Q-test p-value of <img src="https://latex.codecogs.com/png.latex?0.75"> suggests little evidence of heterogeneity; a p-value <img src="https://latex.codecogs.com/png.latex?%3C%200.001"> suggests strong evidence of heterogeneity, prompting investigation of possible pleiotropy. Importantly, heterogeneity is a <em>warning sign</em>, not proof of invalidity — possible explanations include true biological complexity, measurement error, pleiotropy, and population structure. It should trigger further investigation rather than immediate rejection of the analysis.</p>
</section>
<section id="the-mr-egger-intercept-test" class="level3" data-number="11.3.2">
<h3 data-number="11.3.2" class="anchored" data-anchor-id="the-mr-egger-intercept-test"><span class="header-section-number">11.3.2</span> The MR-Egger Intercept Test</h3>
<p>Recall from Part 8 that MR-Egger estimates <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D%20=%20%5Calpha%20+%20%5Cbeta_%7BMR%7D%5Cbeta_%7BGX%7D%20+%20%5Cepsilon">, and the intercept <img src="https://latex.codecogs.com/png.latex?%5Calpha"> measures average directional pleiotropy. The null hypothesis is <img src="https://latex.codecogs.com/png.latex?%5Calpha%20=%200"> (no directional pleiotropy); the alternative is <img src="https://latex.codecogs.com/png.latex?%5Calpha%20%5Cne%200"> (directional pleiotropy present). For example, an intercept of <img src="https://latex.codecogs.com/png.latex?0.001"> with <img src="https://latex.codecogs.com/png.latex?p%20=%200.72"> shows no evidence of pleiotropy, while an intercept of <img src="https://latex.codecogs.com/png.latex?0.035"> with <img src="https://latex.codecogs.com/png.latex?p%20=%200.002"> suggests pleiotropic bias.</p>
</section>
<section id="leave-one-out-analysis" class="level3" data-number="11.3.3">
<h3 data-number="11.3.3" class="anchored" data-anchor-id="leave-one-out-analysis"><span class="header-section-number">11.3.3</span> Leave-One-Out Analysis</h3>
<p>Another popular sensitivity analysis is the leave-one-out procedure: given 20 SNPs, run IVW using all 20, then remove SNP1 and re-run, remove SNP2 and re-run, and so on until every SNP has been excluded once. This identifies influential SNPs — for example, if the full analysis gives <img src="https://latex.codecogs.com/png.latex?0.42"> but removing SNP7 drops the estimate to <img src="https://latex.codecogs.com/png.latex?0.05">, SNP7 is clearly driving the result and deserves closer inspection.</p>
<p>The ideal pattern is that all leave-one-out estimates are similar; the problematic pattern is that one or two SNPs dramatically alter the estimate, potentially signaling horizontal pleiotropy, data problems, or invalid instruments.</p>
</section>
<section id="funnel-plots-scatter-plots-and-forest-plots" class="level3" data-number="11.3.4">
<h3 data-number="11.3.4" class="anchored" data-anchor-id="funnel-plots-scatter-plots-and-forest-plots"><span class="header-section-number">11.3.4</span> Funnel Plots, Scatter Plots, and Forest Plots</h3>
<p>A <strong>funnel plot</strong> plots each SNP’s causal estimate against its precision. Under balanced pleiotropy the plot should be symmetric; under directional pleiotropy it can become asymmetric.</p>
<p>A <strong>scatter plot</strong> places <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGX%7D"> on the x-axis and <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7BGY%7D"> on the y-axis, with each point a SNP, and IVW/MR-Egger regression lines overlaid — useful for visualizing instrument consistency, outliers, and pleiotropic effects.</p>
<p>A <strong>forest plot</strong> displays individual SNP estimates, their confidence intervals, and the combined MR estimate, helping identify outlying SNPs, instrument consistency, and heterogeneity. Forest plots are widely used in published MR studies.</p>
</section>
</section>
<section id="triangulation-of-evidence" class="level2" data-number="11.4">
<h2 data-number="11.4" class="anchored" data-anchor-id="triangulation-of-evidence"><span class="header-section-number">11.4</span> Triangulation of Evidence</h2>
<p>One of the most important ideas in causal inference is <strong>triangulation</strong>: rather than relying on a single result, researchers examine IVW, MR-Egger, weighted median, weighted mode, heterogeneity tests, and leave-one-out analyses together. When all lines of evidence support the same conclusion, confidence increases substantially.</p>
<p><strong>A reassuring example.</strong> IVW = 0.45, MR-Egger = 0.42, Weighted Median = 0.43, Weighted Mode = 0.41; MR-Egger intercept <img src="https://latex.codecogs.com/png.latex?p%20=%200.65">; Cochran’s Q <img src="https://latex.codecogs.com/png.latex?p%20=%200.48">; leave-one-out stable. Interpretation: little evidence of pleiotropy or heterogeneity, strong support for a causal effect.</p>
<p><strong>A concerning example.</strong> IVW = 0.80, MR-Egger = 0.10, Weighted Median = 0.18, Weighted Mode = 0.15; MR-Egger intercept <img src="https://latex.codecogs.com/png.latex?p%20=%200.001">; Cochran’s Q <img src="https://latex.codecogs.com/png.latex?p%20%3C%200.001">; one SNP drives the leave-one-out result. Interpretation: strong evidence of pleiotropy, the IVW estimate is likely biased, and causal conclusions should be interpreted cautiously.</p>
</section>
<section id="how-published-mr-studies-are-typically-reported" class="level2" data-number="11.5">
<h2 data-number="11.5" class="anchored" data-anchor-id="how-published-mr-studies-are-typically-reported"><span class="header-section-number">11.5</span> How Published MR Studies Are Typically Reported</h2>
<p>A standard MR paper usually includes the IVW, MR-Egger, weighted median, and weighted mode estimates; Cochran’s Q; the MR-Egger intercept test; a leave-one-out analysis; and scatter, forest, and funnel plots. These analyses collectively evaluate robustness.</p>
</section>
<section id="the-big-picture-2" class="level2" data-number="11.6">
<h2 data-number="11.6" class="anchored" data-anchor-id="the-big-picture-2"><span class="header-section-number">11.6</span> The Big Picture</h2>
<p>Sensitivity analyses are not optional extras — they are an essential component of Mendelian Randomization. The goal is not simply to produce a causal estimate, but to determine whether that estimate remains credible under a variety of assumptions and potential violations. Strong causal claims require strong supporting evidence, and sensitivity analyses provide it.</p>
</section>
<section id="looking-ahead-9" class="level2" data-number="11.7">
<h2 data-number="11.7" class="anchored" data-anchor-id="looking-ahead-9"><span class="header-section-number">11.7</span> Looking Ahead</h2>
<p>We’ve now covered the major MR estimators and sensitivity analyses used in modern Mendelian Randomization. Part 12 brings everything together in a complete, practical workflow using the <code>TwoSampleMR</code> package in R.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li>Sensitivity analyses evaluate the robustness of MR conclusions; agreement across methods strengthens confidence.</li>
<li>Heterogeneity (via Cochran’s Q) and the MR-Egger intercept both signal possible pleiotropy or invalid instruments.</li>
<li>Leave-one-out analysis identifies individual SNPs that disproportionately drive a result.</li>
<li>Funnel, scatter, and forest plots provide complementary visual diagnostics.</li>
<li>Modern MR studies rely on multiple complementary analyses rather than a single estimator.</li>
</ul>
</blockquote>
</section>
</section>
<section id="part-12-a-complete-mendelian-randomization-workflow-using-twosamplemr" class="level1" data-number="12">
<h1 data-number="12"><span class="header-section-number">12</span> Part 12 — A Complete Mendelian Randomization Workflow Using <code>TwoSampleMR</code></h1>
<p>The previous parts covered the theoretical foundations of MR: correlation versus causation, instrumental variables, the Wald Ratio, IVW, two-sample MR, harmonization, horizontal pleiotropy, MR-Egger, weighted median, weighted mode, and sensitivity analyses. This final part brings everything together in a complete, practical MR analysis using the <code>TwoSampleMR</code> package in R.</p>
<p>The goal is not merely to run software, but to see how each step connects back to the assumptions and concepts covered throughout this series.</p>
<section id="the-overall-workflow" class="level2" data-number="12.1">
<h2 data-number="12.1" class="anchored" data-anchor-id="the-overall-workflow"><span class="header-section-number">12.1</span> The Overall Workflow</h2>
<p>A standard MR analysis consists of six major steps:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BExposure%20GWAS%7D%20%5Crightarrow%20%5Ctext%7BInstrument%20Selection%7D%20%5Crightarrow%20%5Ctext%7BOutcome%20GWAS%7D%20%5Crightarrow%20%5Ctext%7BHarmonization%7D%20%5Crightarrow%20%5Ctext%7BMR%20Analysis%7D%20%5Crightarrow%20%5Ctext%7BSensitivity%20Analyses%7D%20%5Crightarrow%20%5Ctext%7BInterpretation%7D"></p>
</section>
<section id="step-1-install-and-load-required-packages" class="level2" data-number="12.2">
<h2 data-number="12.2" class="anchored" data-anchor-id="step-1-install-and-load-required-packages"><span class="header-section-number">12.2</span> Step 1: Install and Load Required Packages</h2>
<div id="87ae2891" class="cell" data-execution_count="4">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("remotes")</span></span>
<span id="cb6-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remotes::install_github("MRCIEU/TwoSampleMR")</span></span>
<span id="cb6-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("data.table")</span></span>
<span id="cb6-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("dplyr")</span></span>
<span id="cb6-5"></span>
<span id="cb6-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(TwoSampleMR)</span>
<span id="cb6-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(data.table)</span>
<span id="cb6-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>
Attaching package: ‘data.table’


The following object is masked from ‘package:base’:

    %notin%



Attaching package: ‘dplyr’


The following objects are masked from ‘package:data.table’:

    between, first, last


The following objects are masked from ‘package:stats’:

    filter, lag


The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

</code></pre>
</div>
</div>
</section>
<section id="step-2-define-the-scientific-question" class="level2" data-number="12.3">
<h2 data-number="12.3" class="anchored" data-anchor-id="step-2-define-the-scientific-question"><span class="header-section-number">12.3</span> Step 2: Define the Scientific Question</h2>
<p>Every MR analysis begins with a causal hypothesis:</p>
<blockquote class="blockquote">
<p>Does BMI causally increase the risk of Coronary Heart Disease (CHD)?</p>
</blockquote>
<p>Exposure: <strong>BMI</strong>. Outcome: <strong>Coronary Heart Disease</strong>.</p>
</section>
<section id="step-3-obtain-genetic-instruments" class="level2" data-number="12.4">
<h2 data-number="12.4" class="anchored" data-anchor-id="step-3-obtain-genetic-instruments"><span class="header-section-number">12.4</span> Step 3: Obtain Genetic Instruments</h2>
<p>The first task is identifying SNPs associated with the exposure — <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BExposure%7D"> — which become the instrumental variables. Using the IEU OpenGWAS database:</p>
<div id="896e72ca" class="cell" data-execution_count="5">
<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;"># Browse available studies</span></span>
<span id="cb8-2">ao <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">available_outcomes</span>()</span>
<span id="cb8-3"></span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Search for BMI datasets</span></span>
<span id="cb8-5">ao <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb8-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</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;">"body mass index"</span>, trait, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ignore.case =</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;">%&gt;%</span></span>
<span id="cb8-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A GwasInfo: 6 × 27</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">id</th>
<th data-quarto-table-cell-role="th" scope="col">trait</th>
<th data-quarto-table-cell-role="th" scope="col">coverage</th>
<th data-quarto-table-cell-role="th" scope="col">ncase</th>
<th data-quarto-table-cell-role="th" scope="col">group_name</th>
<th data-quarto-table-cell-role="th" scope="col">year</th>
<th data-quarto-table-cell-role="th" scope="col">mr</th>
<th data-quarto-table-cell-role="th" scope="col">author</th>
<th data-quarto-table-cell-role="th" scope="col">sex</th>
<th data-quarto-table-cell-role="th" scope="col">qc_prior_to_upload</th>
<th data-quarto-table-cell-role="th" scope="col">⋯</th>
<th data-quarto-table-cell-role="th" scope="col">ncontrol</th>
<th data-quarto-table-cell-role="th" scope="col">covariates</th>
<th data-quarto-table-cell-role="th" scope="col">subcategory</th>
<th data-quarto-table-cell-role="th" scope="col">category</th>
<th data-quarto-table-cell-role="th" scope="col">ontology</th>
<th data-quarto-table-cell-role="th" scope="col">doi</th>
<th data-quarto-table-cell-role="th" scope="col">note</th>
<th data-quarto-table-cell-role="th" scope="col">study_design</th>
<th data-quarto-table-cell-role="th" scope="col">consortium</th>
<th data-quarto-table-cell-role="th" scope="col">sd</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">⋯</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ebi-a-GCST90103751</td>
<td>Body mass index</td>
<td>NA</td>
<td>NA</td>
<td>public</td>
<td>2022</td>
<td>1</td>
<td>Wong HS</td>
<td>NA</td>
<td>NA</td>
<td>⋯</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td></td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
</tr>
<tr class="even">
<td>ebi-a-GCST90095039</td>
<td>Body mass index</td>
<td>NA</td>
<td>NA</td>
<td>public</td>
<td>2022</td>
<td>1</td>
<td>Fern&lt;U+00E1&gt;ndez-Rhodes L</td>
<td>NA</td>
<td>NA</td>
<td>⋯</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td></td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
</tr>
<tr class="odd">
<td>ebi-a-GCST90095034</td>
<td>Body mass index</td>
<td>NA</td>
<td>NA</td>
<td>public</td>
<td>2022</td>
<td>1</td>
<td>Fern&lt;U+00E1&gt;ndez-Rhodes L</td>
<td>NA</td>
<td>NA</td>
<td>⋯</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td></td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
</tr>
<tr class="even">
<td>ebi-a-GCST90029007</td>
<td>Body mass index</td>
<td>NA</td>
<td>NA</td>
<td>public</td>
<td>2018</td>
<td>1</td>
<td>Loh PR</td>
<td>NA</td>
<td>NA</td>
<td>⋯</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td></td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
</tr>
<tr class="odd">
<td>ebi-a-GCST90025994</td>
<td>Body mass index</td>
<td>NA</td>
<td>NA</td>
<td>public</td>
<td>2021</td>
<td>1</td>
<td>Barton AR</td>
<td>NA</td>
<td>NA</td>
<td>⋯</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td></td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
</tr>
<tr class="even">
<td>ebi-a-GCST90018947</td>
<td>Body mass index</td>
<td>NA</td>
<td>NA</td>
<td>public</td>
<td>2021</td>
<td>1</td>
<td>Sakaue S</td>
<td>NA</td>
<td>NA</td>
<td>⋯</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td></td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Suppose the BMI dataset of interest is <code>ieu-a-2</code>. Extract instruments:</p>
<div id="bca7f04e" class="cell" data-execution_count="6">
<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">exposure_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extract_instruments</span>(</span>
<span id="cb9-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outcomes =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ieu-a-2"</span></span>
<span id="cb9-3">)</span></code></pre></div></div>
</div>
<p><code>extract_instruments()</code> selects SNPs that reach genome-wide significance, <img src="https://latex.codecogs.com/png.latex?P%20%3C%205%20%5Ctimes%2010%5E%7B-8%7D">, against BMI. The output contains SNP IDs, effect alleles, beta coefficients, standard errors, and p-values.</p>
<p>Inspect the instruments:</p>
<div id="74d8a0b1" class="cell" data-execution_count="7">
<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;">head</span>(exposure_dat)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 15</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">id.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">chr.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">pos.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">SNP</th>
<th data-quarto-table-cell-role="th" scope="col">effect_allele.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">other_allele.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">eaf.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">beta.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">se.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">pval.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">samplesize.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">exposure</th>
<th data-quarto-table-cell-role="th" scope="col">mr_keep.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">pval_origin.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">data_source.exposure</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>ieu-a-2</td>
<td>16</td>
<td>53803574</td>
<td>rs1558902</td>
<td>A</td>
<td>T</td>
<td>0.4500</td>
<td>0.0809</td>
<td>0.0030</td>
<td>1.12980e-156</td>
<td>336974</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>ieu-a-2</td>
<td>18</td>
<td>57838401</td>
<td>rs663129</td>
<td>A</td>
<td>G</td>
<td>0.2833</td>
<td>0.0549</td>
<td>0.0034</td>
<td>3.02970e-57</td>
<td>332575</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>ieu-a-2</td>
<td>2</td>
<td>632348</td>
<td>rs13021737</td>
<td>G</td>
<td>A</td>
<td>0.8750</td>
<td>0.0604</td>
<td>0.0039</td>
<td>5.43876e-54</td>
<td>333169</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>ieu-a-2</td>
<td>4</td>
<td>45182527</td>
<td>rs10938397</td>
<td>G</td>
<td>A</td>
<td>0.4333</td>
<td>0.0399</td>
<td>0.0030</td>
<td>1.41710e-40</td>
<td>337092</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>ieu-a-2</td>
<td>1</td>
<td>177889480</td>
<td>rs543874</td>
<td>G</td>
<td>A</td>
<td>0.2667</td>
<td>0.0497</td>
<td>0.0037</td>
<td>2.28718e-40</td>
<td>339078</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>ieu-a-2</td>
<td>6</td>
<td>50865820</td>
<td>rs943005</td>
<td>T</td>
<td>C</td>
<td>0.1000</td>
<td>0.0444</td>
<td>0.0038</td>
<td>4.52376e-31</td>
<td>339197</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
</tr>
</tbody>
</table>
</div>
</div>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Column</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>SNP</code></td>
<td>Variant ID</td>
</tr>
<tr class="even">
<td><code>beta.exposure</code></td>
<td>SNP → Exposure effect</td>
</tr>
<tr class="odd">
<td><code>se.exposure</code></td>
<td>Standard error</td>
</tr>
<tr class="even">
<td><code>effect_allele.exposure</code></td>
<td>Effect allele</td>
</tr>
<tr class="odd">
<td><code>other_allele.exposure</code></td>
<td>Reference allele</td>
</tr>
<tr class="even">
<td><code>pval.exposure</code></td>
<td>GWAS p-value</td>
</tr>
</tbody>
</table>
</section>
<section id="step-4-obtain-outcome-associations" class="level2" data-number="12.5">
<h2 data-number="12.5" class="anchored" data-anchor-id="step-4-obtain-outcome-associations"><span class="header-section-number">12.5</span> Step 4: Obtain Outcome Associations</h2>
<p>Now extract the same SNPs from the outcome GWAS — suppose <code>ieu-a-7</code> corresponds to Coronary Heart Disease:</p>
<div id="25094cb2" class="cell" data-execution_count="8">
<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">outcome_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extract_outcome_data</span>(</span>
<span id="cb11-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">snps =</span> exposure_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>SNP,</span>
<span id="cb11-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outcomes =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ieu-a-7"</span></span>
<span id="cb11-4">)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>Extracting data for 78 SNP(s) from 1 GWAS(s)

Querying id chunk 1 of 1

Querying variant chunk 1 of 2

Querying variant chunk 2 of 2
</code></pre>
</div>
</div>
<p>This provides <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BSNP%7D%20%5Crightarrow%20%5Ctext%7BOutcome%7D"> associations. Inspect the outcome data:</p>
<div id="dcdb5cf7" class="cell" data-execution_count="9">
<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;">head</span>(outcome_dat)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 16</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">SNP</th>
<th data-quarto-table-cell-role="th" scope="col">chr</th>
<th data-quarto-table-cell-role="th" scope="col">pos</th>
<th data-quarto-table-cell-role="th" scope="col">beta.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">se.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">samplesize.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">pval.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">eaf.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">effect_allele.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">other_allele.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">outcome</th>
<th data-quarto-table-cell-role="th" scope="col">id.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">originalname.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">outcome.deprecated</th>
<th data-quarto-table-cell-role="th" scope="col">mr_keep.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">data_source.outcome</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>rs657452</td>
<td>1</td>
<td>49589847</td>
<td>-0.007670</td>
<td>0.0093844</td>
<td>184305</td>
<td>0.4137470</td>
<td>0.566124</td>
<td>G</td>
<td>A</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>ieu-a-7</td>
<td>Coronary heart disease</td>
<td>Coronary heart disease || ||</td>
<td>TRUE</td>
<td>igd</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>rs7531118</td>
<td>1</td>
<td>72837239</td>
<td>0.017675</td>
<td>0.0097331</td>
<td>184305</td>
<td>0.0693745</td>
<td>0.480633</td>
<td>C</td>
<td>T</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>ieu-a-7</td>
<td>Coronary heart disease</td>
<td>Coronary heart disease || ||</td>
<td>TRUE</td>
<td>igd</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>rs17381664</td>
<td>1</td>
<td>78048331</td>
<td>0.016188</td>
<td>0.0102099</td>
<td>184305</td>
<td>0.1128490</td>
<td>0.349349</td>
<td>C</td>
<td>T</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>ieu-a-7</td>
<td>Coronary heart disease</td>
<td>Coronary heart disease || ||</td>
<td>TRUE</td>
<td>igd</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>rs11165643</td>
<td>1</td>
<td>96924097</td>
<td>0.005150</td>
<td>0.0092844</td>
<td>184305</td>
<td>0.5791050</td>
<td>0.553284</td>
<td>T</td>
<td>C</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>ieu-a-7</td>
<td>Coronary heart disease</td>
<td>Coronary heart disease || ||</td>
<td>TRUE</td>
<td>igd</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>rs7550711</td>
<td>1</td>
<td>110082886</td>
<td>-0.048354</td>
<td>0.0305635</td>
<td>184305</td>
<td>0.1136310</td>
<td>0.027650</td>
<td>T</td>
<td>C</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>ieu-a-7</td>
<td>Coronary heart disease</td>
<td>Coronary heart disease || ||</td>
<td>TRUE</td>
<td>igd</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>rs543874</td>
<td>1</td>
<td>177889480</td>
<td>0.007600</td>
<td>0.0117296</td>
<td>184305</td>
<td>0.5170290</td>
<td>0.189189</td>
<td>G</td>
<td>A</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>ieu-a-7</td>
<td>Coronary heart disease</td>
<td>Coronary heart disease || ||</td>
<td>TRUE</td>
<td>igd</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Important columns include <code>beta.outcome</code>, <code>se.outcome</code>, <code>effect_allele.outcome</code>, and <code>pval.outcome</code>.</p>
</section>
<section id="step-5-harmonization" class="level2" data-number="12.6">
<h2 data-number="12.6" class="anchored" data-anchor-id="step-5-harmonization"><span class="header-section-number">12.6</span> Step 5: Harmonization</h2>
<p>Before calculating causal estimates, alleles must be aligned (Part 6):</p>
<blockquote class="blockquote">
<p>Exposure and outcome effects must refer to the same allele.</p>
</blockquote>
<div id="638144b4" class="cell" data-execution_count="10">
<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">harmonised_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">harmonise_data</span>(</span>
<span id="cb14-2">  exposure_dat,</span>
<span id="cb14-3">  outcome_dat</span>
<span id="cb14-4">)</span>
<span id="cb14-5"></span>
<span id="cb14-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(harmonised_dat)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>Harmonising Body mass index || id:ieu-a-2 (ieu-a-2) and Coronary heart disease || id:ieu-a-7 (ieu-a-7)

Removing the following SNPs for being palindromic with intermediate allele frequencies:
rs1558902
</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 36</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">SNP</th>
<th data-quarto-table-cell-role="th" scope="col">effect_allele.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">other_allele.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">effect_allele.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">other_allele.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">beta.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">beta.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">eaf.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">eaf.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">remove</th>
<th data-quarto-table-cell-role="th" scope="col">⋯</th>
<th data-quarto-table-cell-role="th" scope="col">se.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">pval.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">samplesize.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">exposure</th>
<th data-quarto-table-cell-role="th" scope="col">mr_keep.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">pval_origin.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">data_source.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">action</th>
<th data-quarto-table-cell-role="th" scope="col">SNP_index</th>
<th data-quarto-table-cell-role="th" scope="col">mr_keep</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">⋯</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;lgl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>rs10132280</td>
<td>A</td>
<td>C</td>
<td>A</td>
<td>C</td>
<td>-0.0221</td>
<td>-0.012169</td>
<td>0.3333</td>
<td>0.282164</td>
<td>FALSE</td>
<td>⋯</td>
<td>0.0033</td>
<td>1.40088e-11</td>
<td>338856</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
<td>2</td>
<td>1</td>
<td>TRUE</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>rs1016287</td>
<td>C</td>
<td>T</td>
<td>C</td>
<td>T</td>
<td>-0.0228</td>
<td>-0.014087</td>
<td>0.6750</td>
<td>0.699031</td>
<td>FALSE</td>
<td>⋯</td>
<td>0.0033</td>
<td>4.35512e-12</td>
<td>339033</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
<td>2</td>
<td>1</td>
<td>TRUE</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>rs10182181</td>
<td>G</td>
<td>A</td>
<td>G</td>
<td>A</td>
<td>0.0309</td>
<td>0.018295</td>
<td>0.5000</td>
<td>0.473525</td>
<td>FALSE</td>
<td>⋯</td>
<td>0.0029</td>
<td>8.07049e-26</td>
<td>338829</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
<td>2</td>
<td>1</td>
<td>TRUE</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>rs1032524</td>
<td>C</td>
<td>T</td>
<td>C</td>
<td>T</td>
<td>0.0182</td>
<td>0.020795</td>
<td>0.5083</td>
<td>0.512710</td>
<td>FALSE</td>
<td>⋯</td>
<td>0.0029</td>
<td>5.63599e-10</td>
<td>333818</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
<td>2</td>
<td>1</td>
<td>TRUE</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>rs10733682</td>
<td>G</td>
<td>A</td>
<td>G</td>
<td>A</td>
<td>-0.0188</td>
<td>-0.004541</td>
<td>0.5750</td>
<td>0.491116</td>
<td>FALSE</td>
<td>⋯</td>
<td>0.0030</td>
<td>2.45499e-10</td>
<td>336886</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
<td>2</td>
<td>1</td>
<td>TRUE</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>rs10840100</td>
<td>G</td>
<td>A</td>
<td>G</td>
<td>A</td>
<td>0.0206</td>
<td>0.014599</td>
<td>0.7250</td>
<td>0.607618</td>
<td>FALSE</td>
<td>⋯</td>
<td>0.0030</td>
<td>6.66653e-12</td>
<td>339135</td>
<td>Body mass index || id:ieu-a-2</td>
<td>TRUE</td>
<td>reported</td>
<td>igd</td>
<td>2</td>
<td>1</td>
<td>TRUE</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>This automatically matches SNPs, aligns alleles, resolves strand issues, removes problematic SNPs, and excludes ambiguous palindromic variants where necessary.</p>
</section>
<section id="step-6-run-mendelian-randomization" class="level2" data-number="12.7">
<h2 data-number="12.7" class="anchored" data-anchor-id="step-6-run-mendelian-randomization"><span class="header-section-number">12.7</span> Step 6: Run Mendelian Randomization</h2>
<div id="5ecbad5c" class="cell" data-execution_count="11">
<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">mr_results <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr</span>(harmonised_dat)</span>
<span id="cb16-2">mr_results</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>Analysing 'ieu-a-2' on 'ieu-a-7'
</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 5 × 9</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">id.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">id.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">outcome</th>
<th data-quarto-table-cell-role="th" scope="col">exposure</th>
<th data-quarto-table-cell-role="th" scope="col">method</th>
<th data-quarto-table-cell-role="th" scope="col">nsnp</th>
<th data-quarto-table-cell-role="th" scope="col">b</th>
<th data-quarto-table-cell-role="th" scope="col">se</th>
<th data-quarto-table-cell-role="th" scope="col">pval</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>MR Egger</td>
<td>77</td>
<td>0.5480371</td>
<td>0.18668642</td>
<td>4.417059e-03</td>
</tr>
<tr class="even">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>Weighted median</td>
<td>77</td>
<td>0.5020780</td>
<td>0.06963858</td>
<td>5.604734e-13</td>
</tr>
<tr class="odd">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>Inverse variance weighted</td>
<td>77</td>
<td>0.4795636</td>
<td>0.06453223</td>
<td>1.074690e-13</td>
</tr>
<tr class="even">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>Simple mode</td>
<td>77</td>
<td>0.3494593</td>
<td>0.16648719</td>
<td>3.913634e-02</td>
</tr>
<tr class="odd">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>Weighted mode</td>
<td>77</td>
<td>0.4539777</td>
<td>0.14820840</td>
<td>3.029458e-03</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>By default, <code>TwoSampleMR</code> reports IVW, MR-Egger, weighted median, and weighted mode. A typical output:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Method</th>
<th>Estimate</th>
<th>SE</th>
<th>P-value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>IVW</td>
<td>0.42</td>
<td>0.08</td>
<td>0.001</td>
</tr>
<tr class="even">
<td>MR-Egger</td>
<td>0.38</td>
<td>0.15</td>
<td>0.02</td>
</tr>
<tr class="odd">
<td>Weighted Median</td>
<td>0.40</td>
<td>0.10</td>
<td>0.003</td>
</tr>
<tr class="even">
<td>Weighted Mode</td>
<td>0.39</td>
<td>0.12</td>
<td>0.005</td>
</tr>
</tbody>
</table>
<p>All four methods point toward a positive causal effect, which strengthens confidence in the result.</p>
</section>
<section id="step-7-heterogeneity-testing" class="level2" data-number="12.8">
<h2 data-number="12.8" class="anchored" data-anchor-id="step-7-heterogeneity-testing"><span class="header-section-number">12.8</span> Step 7: Heterogeneity Testing</h2>
<div id="88364e67" class="cell" data-execution_count="12">
<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">heterogeneity_results <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_heterogeneity</span>(harmonised_dat)</span>
<span id="cb18-2">heterogeneity_results</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 2 × 8</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">id.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">id.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">outcome</th>
<th data-quarto-table-cell-role="th" scope="col">exposure</th>
<th data-quarto-table-cell-role="th" scope="col">method</th>
<th data-quarto-table-cell-role="th" scope="col">Q</th>
<th data-quarto-table-cell-role="th" scope="col">Q_df</th>
<th data-quarto-table-cell-role="th" scope="col">Q_pval</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>MR Egger</td>
<td>143.8278</td>
<td>75</td>
<td>3.055122e-06</td>
</tr>
<tr class="even">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>Inverse variance weighted</td>
<td>144.1213</td>
<td>76</td>
<td>3.997391e-06</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>A Cochran’s Q p-value of <img src="https://latex.codecogs.com/png.latex?0.62"> indicates little evidence of heterogeneity; a p-value <img src="https://latex.codecogs.com/png.latex?%3C%200.001"> would instead suggest possible pleiotropy or invalid instruments.</p>
</section>
<section id="step-8-test-for-directional-pleiotropy" class="level2" data-number="12.9">
<h2 data-number="12.9" class="anchored" data-anchor-id="step-8-test-for-directional-pleiotropy"><span class="header-section-number">12.9</span> Step 8: Test for Directional Pleiotropy</h2>
<div id="d1253f90" class="cell" data-execution_count="13">
<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">pleiotropy_results <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_pleiotropy_test</span>(harmonised_dat)</span>
<span id="cb19-2">pleiotropy_results</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 7</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">id.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">id.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">outcome</th>
<th data-quarto-table-cell-role="th" scope="col">exposure</th>
<th data-quarto-table-cell-role="th" scope="col">egger_intercept</th>
<th data-quarto-table-cell-role="th" scope="col">se</th>
<th data-quarto-table-cell-role="th" scope="col">pval</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>-0.001908813</td>
<td>0.004879647</td>
<td>0.6967744</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>An intercept p-value of <img src="https://latex.codecogs.com/png.latex?0.75"> indicates little evidence of directional pleiotropy; a p-value of <img src="https://latex.codecogs.com/png.latex?0.002"> would suggest it may be present.</p>
</section>
<section id="step-9-leave-one-out-analysis" class="level2" data-number="12.10">
<h2 data-number="12.10" class="anchored" data-anchor-id="step-9-leave-one-out-analysis"><span class="header-section-number">12.10</span> Step 9: Leave-One-Out Analysis</h2>
<div id="e4ec8225" class="cell" data-execution_count="14">
<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">loo_results <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_leaveoneout</span>(harmonised_dat)</span>
<span id="cb20-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_leaveoneout_plot</span>(loo_results)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<div class="ansi-escaped-output">
<pre>Warning message:

“Removed 1 row containing missing values or values outside the scale range (`geom_point()`).”
</pre>
</div>
</div>
<div class="cell-output cell-output-display">
<pre><code>[[1]]</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/mendelianR/Mendelian_Randomization_files/figure-html/cell-15-output-3.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>If all leave-one-out estimates stay similar, the result is stable; if removing one SNP dramatically changes the estimate, that SNP warrants further investigation.</p>
</section>
<section id="step-10-scatter-plot" class="level2" data-number="12.11">
<h2 data-number="12.11" class="anchored" data-anchor-id="step-10-scatter-plot"><span class="header-section-number">12.11</span> Step 10: Scatter Plot</h2>
<div id="ca085fd3" class="cell" data-execution_count="15">
<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">scatter_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;">mr_scatter_plot</span>(mr_results, harmonised_dat)</span>
<span id="cb22-2">scatter_plot</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>$`ieu-a-2.ieu-a-7`</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/mendelianR/Mendelian_Randomization_files/figure-html/cell-16-output-2.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The plot shows SNP-exposure effects, SNP-outcome effects, and the IVW and MR-Egger regression lines together.</p>
</section>
<section id="step-11-forest-plot" class="level2" data-number="12.12">
<h2 data-number="12.12" class="anchored" data-anchor-id="step-11-forest-plot"><span class="header-section-number">12.12</span> Step 11: Forest Plot</h2>
<div id="299b0037" class="cell" data-execution_count="16">
<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">single_snp_results <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_singlesnp</span>(harmonised_dat)</span>
<span id="cb24-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_forest_plot</span>(single_snp_results)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<div class="ansi-escaped-output">
<pre>Warning message:

“Removed 1 row containing missing values or values outside the scale range (`geom_point()`).”
</pre>
</div>
</div>
<div class="cell-output cell-output-display">
<pre><code>[[1]]</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/mendelianR/Mendelian_Randomization_files/figure-html/cell-17-output-3.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>This helps identify outliers and heterogeneity across individual SNPs.</p>
</section>
<section id="step-12-funnel-plot" class="level2" data-number="12.13">
<h2 data-number="12.13" class="anchored" data-anchor-id="step-12-funnel-plot"><span class="header-section-number">12.13</span> Step 12: Funnel Plot</h2>
<div id="f793b602" class="cell" data-execution_count="17">
<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;">mr_funnel_plot</span>(single_snp_results)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<pre><code>[[1]]</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/mendelianR/Mendelian_Randomization_files/figure-html/cell-18-output-2.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Symmetric plots suggest balanced pleiotropy; asymmetry may indicate directional pleiotropy.</p>
</section>
<section id="a-complete-example-pipeline" class="level2" data-number="12.14">
<h2 data-number="12.14" class="anchored" data-anchor-id="a-complete-example-pipeline"><span class="header-section-number">12.14</span> A Complete Example Pipeline</h2>
<div id="46492ded" class="cell" data-execution_count="18">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" 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;">library</span>(TwoSampleMR)</span>
<span id="cb28-2"></span>
<span id="cb28-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Extract instruments</span></span>
<span id="cb28-4">exposure_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extract_instruments</span>(</span>
<span id="cb28-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outcomes =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ieu-a-2"</span></span>
<span id="cb28-6">)</span>
<span id="cb28-7"></span>
<span id="cb28-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Extract outcomes</span></span>
<span id="cb28-9">outcome_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extract_outcome_data</span>(</span>
<span id="cb28-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">snps =</span> exposure_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>SNP,</span>
<span id="cb28-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outcomes =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ieu-a-7"</span></span>
<span id="cb28-12">)</span>
<span id="cb28-13"></span>
<span id="cb28-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Harmonize</span></span>
<span id="cb28-15">harmonised_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">harmonise_data</span>(</span>
<span id="cb28-16">  exposure_dat,</span>
<span id="cb28-17">  outcome_dat</span>
<span id="cb28-18">)</span>
<span id="cb28-19"></span>
<span id="cb28-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Main MR</span></span>
<span id="cb28-21">mr_results <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr</span>(harmonised_dat)</span>
<span id="cb28-22"></span>
<span id="cb28-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Heterogeneity</span></span>
<span id="cb28-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_heterogeneity</span>(harmonised_dat)</span>
<span id="cb28-25"></span>
<span id="cb28-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pleiotropy</span></span>
<span id="cb28-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_pleiotropy_test</span>(harmonised_dat)</span>
<span id="cb28-28"></span>
<span id="cb28-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Leave-one-out</span></span>
<span id="cb28-30">loo <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_leaveoneout</span>(harmonised_dat)</span>
<span id="cb28-31"></span>
<span id="cb28-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Visualizations</span></span>
<span id="cb28-33"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_scatter_plot</span>(mr_results, harmonised_dat)</span>
<span id="cb28-34"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mr_leaveoneout_plot</span>(loo)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre><code>Extracting data for 78 SNP(s) from 1 GWAS(s)

Querying id chunk 1 of 1

Querying variant chunk 1 of 2

Querying variant chunk 2 of 2

Harmonising Body mass index || id:ieu-a-2 (ieu-a-2) and Coronary heart disease || id:ieu-a-7 (ieu-a-7)

Removing the following SNPs for being palindromic with intermediate allele frequencies:
rs1558902

Analysing 'ieu-a-2' on 'ieu-a-7'
</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 2 × 8</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">id.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">id.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">outcome</th>
<th data-quarto-table-cell-role="th" scope="col">exposure</th>
<th data-quarto-table-cell-role="th" scope="col">method</th>
<th data-quarto-table-cell-role="th" scope="col">Q</th>
<th data-quarto-table-cell-role="th" scope="col">Q_df</th>
<th data-quarto-table-cell-role="th" scope="col">Q_pval</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>MR Egger</td>
<td>143.8278</td>
<td>75</td>
<td>3.055122e-06</td>
</tr>
<tr class="even">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>Inverse variance weighted</td>
<td>144.1213</td>
<td>76</td>
<td>3.997391e-06</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 7</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">id.exposure</th>
<th data-quarto-table-cell-role="th" scope="col">id.outcome</th>
<th data-quarto-table-cell-role="th" scope="col">outcome</th>
<th data-quarto-table-cell-role="th" scope="col">exposure</th>
<th data-quarto-table-cell-role="th" scope="col">egger_intercept</th>
<th data-quarto-table-cell-role="th" scope="col">se</th>
<th data-quarto-table-cell-role="th" scope="col">pval</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ieu-a-2</td>
<td>ieu-a-7</td>
<td>Coronary heart disease || id:ieu-a-7</td>
<td>Body mass index || id:ieu-a-2</td>
<td>-0.001908813</td>
<td>0.004879647</td>
<td>0.6967744</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<pre><code>$`ieu-a-2.ieu-a-7`</code></pre>
</div>
<div class="cell-output cell-output-stderr">
<div class="ansi-escaped-output">
<pre>Warning message:

“Removed 1 row containing missing values or values outside the scale range (`geom_point()`).”
</pre>
</div>
</div>
<div class="cell-output cell-output-display">
<pre><code>[[1]]</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/mendelianR/Mendelian_Randomization_files/figure-html/cell-19-output-7.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/mendelianR/Mendelian_Randomization_files/figure-html/cell-19-output-8.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<blockquote class="blockquote">
<p><strong>A note on <code>ieugwasr</code> API changes.</strong> Running <code>extract_instruments()</code> against the live OpenGWAS API can currently fail with an error such as <code>unused argument (x_api_source = x_api_source_header())</code>, because a mismatch between the installed <code>TwoSampleMR</code> and <code>ieugwasr</code> package versions changes the function signature for <code>tophits()</code>. If you hit this, update both packages to their latest GitHub versions (<code>remotes::install_github("MRCIEU/ieugwasr")</code> and <code>remotes::install_github("MRCIEU/TwoSampleMR")</code>) before re-running the pipeline above.</p>
</blockquote>
</section>
<section id="how-results-are-usually-reported" class="level2" data-number="12.15">
<h2 data-number="12.15" class="anchored" data-anchor-id="how-results-are-usually-reported"><span class="header-section-number">12.15</span> How Results Are Usually Reported</h2>
<p>A typical conclusion might read:</p>
<blockquote class="blockquote">
<p>Genetically predicted BMI was positively associated with coronary heart disease risk. The IVW estimate suggested a significant causal effect. Sensitivity analyses using MR-Egger, weighted median, and weighted mode methods produced similar estimates. There was little evidence of directional pleiotropy based on the MR-Egger intercept test, and leave-one-out analyses indicated that no single SNP drove the observed association.</p>
</blockquote>
<p>This is the style commonly seen in published MR studies.</p>
</section>
<section id="common-mistakes" class="level2" data-number="12.16">
<h2 data-number="12.16" class="anchored" data-anchor-id="common-mistakes"><span class="header-section-number">12.16</span> Common Mistakes</h2>
<ul>
<li><strong>Using weak instruments</strong> — weak SNPs produce unstable estimates.</li>
<li><strong>Ignoring harmonization</strong> — incorrect allele alignment can reverse causal conclusions.</li>
<li><strong>Reporting only IVW</strong> — robust methods should also be presented.</li>
<li><strong>Ignoring pleiotropy tests</strong> — sensitivity analyses are essential.</li>
<li><strong>Overstating causality</strong> — MR provides evidence for causality, but remains subject to its assumptions and limitations.</li>
</ul>
</section>
<section id="the-big-picture-3" class="level2" data-number="12.17">
<h2 data-number="12.17" class="anchored" data-anchor-id="the-big-picture-3"><span class="header-section-number">12.17</span> The Big Picture</h2>
<p>A complete MR study is much more than calculating a single causal estimate. Researchers must select instruments, harmonize data, estimate causal effects, test assumptions, evaluate robustness, and interpret results carefully. The strength of MR comes not from a single method, but from combining multiple complementary analyses into a coherent causal inference framework.</p>
</section>
<section id="final-summary-of-the-series" class="level2" data-number="12.18">
<h2 data-number="12.18" class="anchored" data-anchor-id="final-summary-of-the-series"><span class="header-section-number">12.18</span> Final Summary of the Series</h2>
<p>Across these twelve parts we covered: correlation versus causation, Mendelian Randomization, instrumental variables, the Wald Ratio, IVW estimation, two-sample MR, harmonization, horizontal pleiotropy, MR-Egger, weighted median, weighted mode, sensitivity analyses, and the complete MR workflow. Together, these concepts form the foundation of modern Mendelian Randomization and causal inference in statistical genetics.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways</strong></p>
<ul>
<li><code>TwoSampleMR</code> provides a complete framework for Mendelian Randomization analyses in R.</li>
<li>Instrument selection comes first; harmonization is essential before estimation.</li>
<li>IVW is typically the primary analysis, with MR-Egger, weighted median, and weighted mode providing robustness checks.</li>
<li>Sensitivity analyses (heterogeneity, pleiotropy tests, leave-one-out) evaluate whether MR assumptions are being violated.</li>
<li>Modern MR studies rely on multiple complementary methods rather than a single estimate — and careful interpretation matters as much as the statistical estimation itself.</li>
</ul>
</blockquote>


</section>
</section>

 ]]></description>
  <category>Genetics</category>
  <category>Epidemiology</category>
  <category>Mendelian Randomization</category>
  <category>Tutorial</category>
  <guid>https://bntechie.github.io/tutorials/mendelianR/Mendelian_Randomization.html</guid>
  <pubDate>Mon, 15 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>The Covariance Matrix in Association Testing</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/covariance_matrix/Covariance_matrix.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/covariance_matrix/images/covariance-matrix.svg" alt="A 3x3 covariance matrix heatmap with the diagonal (variances) highlighted in amber and off-diagonal covariances shaded by strength" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The object at the center of every case in this tutorial: a covariance matrix’s diagonal describes each observation’s own variance, but it’s the off-diagonal terms – the part “independence” assumes away – that decide whether a p-value can be trusted.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">Covariance</span> <span class="tag">Mixed Models</span> <span class="tag">GRM</span> <span class="tag">R</span></p>
</div>
<p>Very often atatistical models fail because we assume observations are independent when they are not. Repeated measurements from the same patient, genetic similarity between individuals, longitudinal studies, family data, spatial observations, and multivariate phenotypes all introduce correlation. Ignoring these dependencies produces misleading standard errors, inflated false-positive rates, and unreliable inference.</p>
<p>The mathematical object that describes these dependencies is the covariance matrix. It summarizes not only how variable each observation is, but also how every pair of observations varies together. Once that covariance structure is specified, many seemingly different statistical methods—from ordinary least squares to generalized least squares, linear mixed models, generalized estimating equations, phylogenetic regression, and modern GWAS methods—become variations of the same underlying framework.</p>
<blockquote class="blockquote">
<p><strong>In one sentence:</strong> a covariance matrix tells a statistical test which observations are allowed to be treated as independent, and every association test is, underneath, a decision about that matrix.</p>
</blockquote>
<section id="what-a-covariance-matrix-actually-is" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="what-a-covariance-matrix-actually-is"><span class="header-section-number">1</span> What a covariance matrix actually is</h2>
<p>For a random vector <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7By%7D%20=%20(y_1,%20%5Cdots,%20y_n)%5E%5Ctop">, the covariance matrix <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D"> collects every pairwise covariance:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cboldsymbol%7B%5CSigma%7D_%7Bij%7D%20=%20%5Ctext%7BCov%7D(y_i,%20y_j)%20=%20E%5B(y_i%20-%20%5Cmu_i)(y_j%20-%20%5Cmu_j)%5D%0A"></p>
<p>The diagonal holds variances, <img src="https://latex.codecogs.com/png.latex?%5CSigma_%7Bii%7D%20=%20%5Ctext%7BVar%7D(y_i)">. The off-diagonal holds the covariances between pairs.</p>
<blockquote class="blockquote">
<p><strong>Why not just track variances?</strong> Because variance alone tells you how much a single variable moves. It says nothing about whether two variables move <em>together</em>. Two traits can each have large variance and still be uncorrelated, or have small variance and be almost perfectly redundant. The off-diagonal is where all the structure lives.</p>
</blockquote>
<p>A quick simulated illustration: three correlated traits.</p>
<div id="99ca85d2-831a-4708-8176-d06f5e8cd581" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:59:48.851001Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:59:48.841376Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:59:48.998286Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:59:48.993899Z&quot;}}" data-execution_count="1">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-2"></span>
<span id="cb1-3">Sigma_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;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb1-4">  <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;">0.7</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="cb1-5">  <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</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;">0.2</span>,</span>
<span id="cb1-6">  <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;">1.0</span></span>
<span id="cb1-7">), <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;">3</span>)</span>
<span id="cb1-8"></span>
<span id="cb1-9">Y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> MASS<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;">mvrnorm</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</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;">mu =</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;">0</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;">Sigma =</span> Sigma_true)</span>
<span id="cb1-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</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;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trait1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trait2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trait3"</span>)</span>
<span id="cb1-11"></span>
<span id="cb1-12"><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;">cov</span>(Y), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 3 × 3 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">trait1</th>
<th data-quarto-table-cell-role="th" scope="col">trait2</th>
<th data-quarto-table-cell-role="th" scope="col">trait3</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">trait1</th>
<td>1.04</td>
<td>0.70</td>
<td>0.09</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">trait2</th>
<td>0.70</td>
<td>0.99</td>
<td>0.26</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">trait3</th>
<td>0.09</td>
<td>0.26</td>
<td>1.13</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The sample covariance recovers the input structure: trait1 and trait2 move together (0.7), trait3 is nearly independent of trait1 (0.1).</p>
</section>
<section id="why-the-covariance-matrix-matters-for-statistical-testing" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="why-the-covariance-matrix-matters-for-statistical-testing"><span class="header-section-number">2</span> Why the covariance matrix matters for statistical testing</h2>
<p>Every standard test statistic (t-test, F-test, GWAS Wald test) is built assuming a specific <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D"> for the residuals or the samples. The two default assumptions are:</p>
<ol type="1">
<li><strong>Independence</strong>: <img src="https://latex.codecogs.com/png.latex?%5CSigma_%7Bij%7D%20=%200"> for <img src="https://latex.codecogs.com/png.latex?i%20%5Cneq%20j">.</li>
<li><strong>Homoscedasticity</strong>: <img src="https://latex.codecogs.com/png.latex?%5CSigma_%7Bii%7D%20=%20%5Csigma%5E2"> for all <img src="https://latex.codecogs.com/png.latex?i">.</li>
</ol>
<p>Together these collapse <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D"> to <img src="https://latex.codecogs.com/png.latex?%5Csigma%5E2%20%5Cmathbf%7BI%7D">, the identity matrix scaled by a constant. Ordinary least squares, the standard GWAS regression, and the standard t-test all silently assume this.</p>
<blockquote class="blockquote">
<p><strong>What breaks when that assumption is wrong?</strong> Nothing about the point estimate. The regression coefficient <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta"> stays unbiased. What breaks is the <strong>standard error</strong>, because the standard OLS variance formula <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(%5Chat%5Cbeta)%20=%20%5Csigma%5E2%20(X%5E%5Ctop%20X)%5E%7B-1%7D"> is only correct when <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D%20=%20%5Csigma%5E2%5Cmathbf%7BI%7D">. If samples are actually correlated, the true variance of <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta"> is <img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7BVar%7D(%5Chat%5Cbeta)%20=%20(X%5E%5Ctop%20X)%5E%7B-1%7D%20X%5E%5Ctop%20%5Cboldsymbol%7B%5CSigma%7D%20X%20(X%5E%5Ctop%20X)%5E%7B-1%7D%0A"> Plugging in the wrong (diagonal) <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D"> gives standard errors that are too small, meaning inflated test statistics, meaning false positives.</p>
</blockquote>
<p>This is the single mechanism behind population stratification in GWAS, pseudoreplication in phylogenetic comparative methods, and the multiple-testing correlation problem in fine-mapping. Different names, same incorrect assumption.</p>
</section>
<section id="association-testing-under-different-covariance-structures" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="association-testing-under-different-covariance-structures"><span class="header-section-number">3</span> Association testing under different covariance structures</h2>
<p>The general form of an association test is a generalized least squares (GLS) problem:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%5Cbeta%20=%20(X%5E%5Ctop%20%5Cboldsymbol%7B%5CSigma%7D%5E%7B-1%7D%20X)%5E%7B-1%7D%20X%5E%5Ctop%20%5Cboldsymbol%7B%5CSigma%7D%5E%7B-1%7D%20y%0A"></p>
<p>which reduces to ordinary least squares when <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D%20=%20%5Csigma%5E2%5Cmathbf%7BI%7D">. Every case below is the same equation with a different <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D"> plugged in.</p>
<section id="case-1-independent-samples-the-textbook-gwas-test" class="level3" data-number="3.1">
<h3 data-number="3.1" class="anchored" data-anchor-id="case-1-independent-samples-the-textbook-gwas-test"><span class="header-section-number">3.1</span> Case 1 — independent samples (the textbook GWAS test)</h3>
<p>If individuals are unrelated and drawn from a single population, <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D%20=%20%5Csigma%5E2%20%5Cmathbf%7BI%7D"> is a reasonable approximation, and a simple linear model per variant is valid:</p>
<div id="83a06a82-5ca6-4042-81b4-0bb407324363" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:59:49.092022Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:59:49.005925Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:59:49.143426Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:59:49.141245Z&quot;}}" data-execution_count="2">
<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 <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="cb2-2">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;">rbinom</span>(n, <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.3</span>)</span>
<span id="cb2-3">phenotype <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 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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n)</span>
<span id="cb2-4"></span>
<span id="cb2-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;">lm</span>(phenotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> genotype)</span>
<span id="cb2-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(fit)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>coefficients</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A matrix: 2 × 4 of type dbl</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">Estimate</th>
<th data-quarto-table-cell-role="th" scope="col">Std. Error</th>
<th data-quarto-table-cell-role="th" scope="col">t value</th>
<th data-quarto-table-cell-role="th" scope="col">Pr(&gt;|t|)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">(Intercept)</th>
<td>-0.001616378</td>
<td>0.04417016</td>
<td>-0.03659433</td>
<td>9.708158e-01</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">genotype</th>
<td>0.327975887</td>
<td>0.04923014</td>
<td>6.66209569</td>
<td>4.454492e-11</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>No hidden structure, no correction needed. The standard GWAS Wald test is designed for such cases.</p>
</section>
<section id="case-2-cryptic-relatedness-and-population-stratification" class="level3" data-number="3.2">
<h3 data-number="3.2" class="anchored" data-anchor-id="case-2-cryptic-relatedness-and-population-stratification"><span class="header-section-number">3.2</span> Case 2 — cryptic relatedness and population stratification</h3>
<p>In reality cohorts are never fully unrelated, and subgroups can differ in both allele frequency and phenotype mean. This induces off-diagonal covariance between individuals that correlates with genotype, which is exactly the condition under which OLS standard errors become invalid.</p>
<p>We simulate two subpopulations with different means and a genotype frequency difference:</p>
<div id="6188d1ea-530e-49a1-89c1-bf8cb6af4cc4" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:59:49.148747Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:59:49.147191Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:59:49.178744Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:59:49.176618Z&quot;}}" data-execution_count="3">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb3-2">n <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="cb3-3">pop <span class="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;">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="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="cb3-4"></span>
<span id="cb3-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># allele frequency differs by population -&gt; stratification</span></span>
<span id="cb3-6">freq <span class="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>(pop <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="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.4</span>)</span>
<span id="cb3-7">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;">rbinom</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, freq)</span>
<span id="cb3-8"></span>
<span id="cb3-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># phenotype differs by population for reasons unrelated to genotype</span></span>
<span id="cb3-10">phenotype <span class="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>(pop <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;">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 class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb3-11"></span>
<span id="cb3-12">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;">lm</span>(phenotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> genotype)</span>
<span id="cb3-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(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;">"genotype"</span>, ]</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>Estimate</dt><dd>0.36051672383449</dd><dt>Std. Error</dt><dd>0.0312442835871719</dd><dt>t value</dt><dd>11.5386458719287</dd><dt>Pr(&gt;|t|)</dt><dd>5.30984934684389e-29</dd></dl>
</div>
</div>
<p>Here <code>genotype</code> picks up a spurious association purely because it tags population membership, not because it affects the phenotype. The fix is to model the covariance directly, either with a genomic relationship matrix (GRM) in a mixed model, or with fixed-effect covariates (PCs) that absorb the structure. The mixed-model version:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ay%20=%20X%5Cbeta%20+%20Zu%20+%20%5Cepsilon,%20%5Cquad%20u%20%5Csim%20N(0,%20%5Csigma%5E2_g%20%5Cmathbf%7BK%7D),%20%5Cquad%20%5Cepsilon%20%5Csim%20N(0,%20%5Csigma%5E2_e%20%5Cmathbf%7BI%7D)%0A"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7BK%7D"> is the GRM: <img src="https://latex.codecogs.com/png.latex?K_%7Bij%7D"> estimates genome-wide relatedness between individuals <img src="https://latex.codecogs.com/png.latex?i"> and <img src="https://latex.codecogs.com/png.latex?j"> from marker data. This is exactly <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D"> built from data instead of assumed to be diagonal.</p>
<div id="80c255a8-7f8d-4b01-bbd6-cefc022713a4" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:59:49.184124Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:59:49.182015Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:59:50.591002Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:59:50.588855Z&quot;}}" data-execution_count="4">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># toy GRM from a small marker panel, standardised as in GCTA/GEMMA.</span></span>
<span id="cb4-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Crucially, these markers must actually carry the population signal --</span></span>
<span id="cb4-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a marker panel with the same allele frequency in both groups would</span></span>
<span id="cb4-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># produce a GRM blind to the very structure we're trying to correct for.</span></span>
<span id="cb4-5">marker_freq_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;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</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.15</span>)</span>
<span id="cb4-6">marker_freq_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;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</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.45</span>)</span>
<span id="cb4-7">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;">sapply</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;">200</span>), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(j) {</span>
<span id="cb4-8">  f <span class="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>(pop <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>, marker_freq_A[j], marker_freq_B[j])</span>
<span id="cb4-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbinom</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, f)</span>
<span id="cb4-10">})</span>
<span id="cb4-11">markers_std <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(markers)</span>
<span id="cb4-12">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;">tcrossprod</span>(markers_std) <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>(markers_std)</span>
<span id="cb4-13"></span>
<span id="cb4-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># correcting the naive test with the top structure-capturing PCs of K</span></span>
<span id="cb4-15">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;">eigen</span>(K)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>vectors[, <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="cb4-16">corrected <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lm</span>(phenotype <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> pcs)</span>
<span id="cb4-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(corrected)<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;">"genotype"</span>, ]</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>Estimate</dt><dd>0.0332531649087993</dd><dt>Std. Error</dt><dd>0.0267829897746121</dd><dt>t value</dt><dd>1.24157777711286</dd><dt>Pr(&gt;|t|)</dt><dd>0.214684689209704</dd></dl>
</div>
</div>
<p>Adding the components that summarise <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7BK%7D"> absorbs the stratification signal and pulls the genotype effect back toward the null. Tools like GEMMA, SAIGE, and regenie fit the full mixed model rather than a PC approximation, but the logic is identical: replace the identity covariance with <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7BK%7D">.</p>
</section>
<section id="case-3-non-independent-taxa-pgls" class="level3" data-number="3.3">
<h3 data-number="3.3" class="anchored" data-anchor-id="case-3-non-independent-taxa-pgls"><span class="header-section-number">3.3</span> Case 3 — non-independent taxa: PGLS</h3>
<p>This scenario also appears in other fields. In a comparative dataset across species, closely related species resemble each other for reasons that have nothing to do with the trait being tested — shared evolutionary history, not shared biology of interest. Ordinary regression treats each species as an independent data point, so the effective sample size is inflated and p-values are anti-conservative.</p>
<p>Phylogenetic generalised least squares replaces <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D%20=%20%5Csigma%5E2%5Cmathbf%7BI%7D"> with a covariance matrix derived from the phylogeny, typically under Brownian motion: <img src="https://latex.codecogs.com/png.latex?%5CSigma_%7Bij%7D"> is the shared branch length from the root to the most recent common ancestor of species <img src="https://latex.codecogs.com/png.latex?i"> and <img src="https://latex.codecogs.com/png.latex?j">.</p>
<div id="89a7964f-8c29-4a6c-8636-c6547243caf4" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:59:50.596186Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:59:50.594464Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:59:50.768815Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:59:50.766646Z&quot;}}" data-execution_count="5">
<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;">library</span>(ape)</span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(nlme)</span>
<span id="cb5-3"></span>
<span id="cb5-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;">3</span>)</span>
<span id="cb5-5">tree <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rtree</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>)</span>
<span id="cb5-6">trait_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;">rTraitCont</span>(tree, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BM"</span>)</span>
<span id="cb5-7">trait_y <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="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> trait_x[tree<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tip.label] <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;">rTraitCont</span>(tree, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BM"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sigma =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb5-8"></span>
<span id="cb5-9">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;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">species =</span> tree<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tip.label, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> trait_x[tree<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tip.label], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> trait_y)</span>
<span id="cb5-10"></span>
<span id="cb5-11">naive_ols <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</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> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> d)</span>
<span id="cb5-12">pgls_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;">gls</span>(y <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;">data =</span> d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">correlation =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">corBrownian</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phy =</span> tree, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">form =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>species))</span>
<span id="cb5-13"></span>
<span id="cb5-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(naive_ols)<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;">"x"</span>, ]</span>
<span id="cb5-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(pgls_fit)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tTable[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>, ]</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>Estimate</dt><dd>0.887154063958009</dd><dt>Std. Error</dt><dd>1.95739468827265</dd><dt>t value</dt><dd>0.453232078983979</dd><dt>Pr(&gt;|t|)</dt><dd>0.653874585786409</dd></dl>
</div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>Value</dt><dd>1.3394774022645</dd><dt>Std.Error</dt><dd>1.3131699537816</dd><dt>t-value</dt><dd>1.02003354433076</dd><dt>p-value</dt><dd>0.316445575574491</dd></dl>
</div>
</div>
<p>Same data, two different assumed covariance matrices, two different standard errors on the same point estimate. This is the direct cousin of Case 2: relatedness there is genetic and pairwise (the GRM), relatedness here is phylogenetic and hierarchical (branch-length covariance), but the correction mechanism — swap <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7BI%7D"> for the real <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D"> — is the same equation.</p>
</section>
<section id="case-4-correlated-variants-joint-testing-and-colocalization" class="level3" data-number="3.4">
<h3 data-number="3.4" class="anchored" data-anchor-id="case-4-correlated-variants-joint-testing-and-colocalization"><span class="header-section-number">3.4</span> Case 4 — correlated variants: joint testing and colocalization</h3>
<p>The covariance problem also shows up across variants rather than across samples. Nearby SNPs in linkage disequilibrium (LD) have correlated genotypes, so their marginal association test statistics are correlated even under the null. Ignoring this inflates the effective number of independent tests and misleads fine-mapping.</p>
<p>The LD matrix <img src="https://latex.codecogs.com/png.latex?R"> (correlation between genotypes at variants <img src="https://latex.codecogs.com/png.latex?j"> and <img src="https://latex.codecogs.com/png.latex?k">) plays the role of <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D"> here. A joint (multi-SNP) test statistic is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cchi%5E2_%7B%5Ctext%7Bjoint%7D%7D%20=%20%5Cmathbf%7Bz%7D%5E%5Ctop%20R%5E%7B-1%7D%20%5Cmathbf%7Bz%7D%0A"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7Bz%7D"> is the vector of marginal Wald z-scores. This is the same GLS logic again, just applied to summary statistics instead of raw phenotypes:</p>
<div id="e85fc665-a673-4f11-9b02-a4c4b76e5d9d" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:59:50.773579Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:59:50.771574Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:59:50.797944Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:59:50.796115Z&quot;}}" data-execution_count="6">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb6-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># simulate LD between 5 variants</span></span>
<span id="cb6-3">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;">matrix</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</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;">5</span>); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diag</span>(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;">1</span></span>
<span id="cb6-4">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;">as.numeric</span>(MASS<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;">mvrnorm</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;">mu =</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;">0</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;">0</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;">Sigma =</span> R))</span>
<span id="cb6-5"></span>
<span id="cb6-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># naive: treat as independent</span></span>
<span id="cb6-7">chisq_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>(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>
<span id="cb6-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pchisq</span>(chisq_naive, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</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;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb6-9"></span>
<span id="cb6-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># correct: account for LD covariance</span></span>
<span id="cb6-11">chisq_joint <span class="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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</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;">solve</span>(R) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> z)</span>
<span id="cb6-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pchisq</span>(chisq_joint, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</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;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
0.0670792649358373
</div>
<div class="cell-output cell-output-display">
0.0175917963452512
</div>
</div>
<p><code>coloc.abf</code> and conditional/joint (COJO) analyses both hinge on getting this <img src="https://latex.codecogs.com/png.latex?R"> right; a mismatched LD reference panel is the single most common cause of spurious colocalization or fine-mapping results.</p>
</section>
</section>
<section id="the-pattern-across-all-four-cases" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="the-pattern-across-all-four-cases"><span class="header-section-number">4</span> The pattern across all four cases</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
</colgroup>
<thead>
<tr class="header">
<th>Case</th>
<th>What violates independence</th>
<th>Covariance matrix used</th>
<th>Fix</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Unrelated individuals</td>
<td>none</td>
<td><img src="https://latex.codecogs.com/png.latex?%5Csigma%5E2%20%5Cmathbf%7BI%7D"></td>
<td>plain OLS/Wald test</td>
</tr>
<tr class="even">
<td>Cryptic relatedness / stratification</td>
<td>shared ancestry between individuals</td>
<td>GRM <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7BK%7D"></td>
<td>linear mixed model</td>
</tr>
<tr class="odd">
<td>Cross-species comparison</td>
<td>shared phylogenetic history</td>
<td>Brownian-motion tree covariance</td>
<td>PGLS</td>
</tr>
<tr class="even">
<td>Variants in LD</td>
<td>correlated genotypes across markers</td>
<td>LD matrix <img src="https://latex.codecogs.com/png.latex?R"></td>
<td>joint/conditional test, colocalization</td>
</tr>
</tbody>
</table>
<p>Every row is the same generalized least squares equation with a different <img src="https://latex.codecogs.com/png.latex?%5Cboldsymbol%7B%5CSigma%7D">. Therefore, whenever a test looks “too significant” relative to intuition, the first thing to check is not the effect size but whether the covariance structure of the data was estimated correctly.</p>
</section>
<section id="further-reading" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="further-reading"><span class="header-section-number">5</span> Further reading</h2>
<p>Yang, Lee, Goddard &amp; Visscher (2011). GCTA: A tool for genome-wide complex trait analysis. American Journal of Human Genetics, 88(1), 76–82. https://doi.org/10.1016/j.ajhg.2010.11.011</p>
<p>Freckleton, Harvey &amp; Pagel (2002). Phylogenetic analysis and comparative data: a test and review of evidence. American Naturalist, 160(6), 712–726. https://doi.org/10.1086/343873</p>
<p>Yang, Ferreira, Morris, et al.&nbsp;(2012). Conditional and joint multiple-SNP analysis of GWAS summary statistics identifies additional variants influencing complex traits. Nature Genetics, 44(4), 369–375. https://doi.org/10.1038/ng.2213</p>


</section>

 ]]></description>
  <category>Statistical Genetics</category>
  <category>GWAS</category>
  <category>Mixed Models</category>
  <category>R</category>
  <guid>https://bntechie.github.io/tutorials/covariance_matrix/Covariance_matrix.html</guid>
  <pubDate>Sun, 14 Jun 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/covariance_matrix/images/covariance-matrix.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Ridge and Lasso Regression</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/ridge_lasso/ridge_lasso_tutorial.html</link>
  <description><![CDATA[ 




<p>Ridge and lasso are the two workhorse methods for fitting a linear model when you have many predictors, some of them correlated, and ordinary least squares (OLS) starts to behave badly. Both add a penalty term to the regression objective; they differ in exactly one detail — whether that penalty is squared or absolute — and that single difference changes everything about how the two methods behave.</p>
<p>This tutorial builds both from scratch: the math, the geometry behind why lasso zeroes out coefficients and ridge doesn’t, and a full R implementation of each, checked against closed-form solutions and OLS along the way.</p>
<section id="why-plain-linear-regression-breaks-down" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Why Plain Linear Regression Breaks Down</h1>
<blockquote class="blockquote">
<p><strong>If OLS already minimizes the residual sum of squares, why would we want anything else?</strong> Because “minimizes the training residual” and “gives a trustworthy, stable estimate” are not the same promise. OLS keeps that promise only when predictors are roughly independent and there’s plenty of data relative to the number of predictors. Neither is guaranteed in practice.</p>
</blockquote>
<p>Real predictor sets are rarely independent. Two variables measuring related things — income and years of education, or two neighboring genetic markers in the same region of a chromosome — carry overlapping information. When predictors are highly correlated, OLS has to arbitrarily decide how to split credit between them, and that split is extremely sensitive to the specific noise in your sample.</p>
<p>We can see this directly. Simulate a 10-predictor design with two “correlated blocks” of 4 predictors each (correlation 0.85 within each block) plus 2 independent predictors, only three of which actually affect the outcome.</p>
<div id="cb6e2e8e" class="cell" data-execution_count="1">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Build a 10-predictor design matrix with two correlated "LD-like" blocks</span></span>
<span id="cb1-4"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## of 4 predictors each (within-block correlation 0.85) plus 2 independent</span></span>
<span id="cb1-5"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## noise predictors -- deliberately mimicking correlated genotype blocks.</span></span>
<span id="cb1-6">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;">10</span></span>
<span id="cb1-7">n <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="cb1-8"></span>
<span id="cb1-9">Sigma <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diag</span>(p)</span>
<span id="cb1-10">block1 <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;">4</span>; block2 <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 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>
<span id="cb1-11">Sigma[block1, block1] <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.85</span></span>
<span id="cb1-12">Sigma[block2, block2] <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.85</span></span>
<span id="cb1-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diag</span>(Sigma) <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-14"></span>
<span id="cb1-15"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Sample correlated predictors via the Cholesky factor of Sigma</span></span>
<span id="cb1-16">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;">chol</span>(Sigma)</span>
<span id="cb1-17">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;">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> p), n, p)</span>
<span id="cb1-18">X <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> Z <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> L</span>
<span id="cb1-19">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;">scale</span>(X)                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># standardize columns</span></span>
<span id="cb1-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</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;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"X"</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)</span>
<span id="cb1-21"></span>
<span id="cb1-22"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## True effects: only the first predictor in each correlated block, plus</span></span>
<span id="cb1-23"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## one of the independent noise predictors, actually affect the outcome</span></span>
<span id="cb1-24">true_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;">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;">0</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;">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;">2</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;">0</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;">1.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb1-25">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.vector</span>(X <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> true_beta <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;">rnorm</span>(n, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb1-26"></span>
<span id="cb1-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Correlation within block 1 (X1-X4):</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>)</span>
<span id="cb1-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</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;">cor</span>(X[, block1]), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb1-29"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">True beta:"</span>, true_beta, <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>)</span>
<span id="cb1-30"></span>
<span id="cb1-31"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">saveRDS</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;">X =</span> X, <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;">true_beta =</span> true_beta, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Sigma =</span> Sigma), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"reg_data.rds"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Correlation within block 1 (X1-X4):
     X1   X2   X3   X4
X1 1.00 0.85 0.82 0.84
X2 0.85 1.00 0.84 0.85
X3 0.82 0.84 1.00 0.84
X4 0.84 0.85 0.84 1.00

True beta: 3 0 0 0 -2 0 0 0 1.5 0 </code></pre>
</div>
</div>
<p>X1–X4 and X5–X8 form two tight correlated blocks, exactly the kind of structure that causes trouble. Only X1, X5, and X9 have a real effect on the outcome — everything else is either a correlated “twin” of a real predictor, or pure noise.</p>
<section id="ols-instability-under-correlated-predictors" class="level2" data-number="1.1">
<h2 data-number="1.1" class="anchored" data-anchor-id="ols-instability-under-correlated-predictors"><span class="header-section-number">1.1</span> 1.1 OLS instability under correlated predictors</h2>
<p>Refit OLS 300 times on fresh draws of the outcome (same design matrix each time) and look at how much the estimated coefficients bounce around.</p>
<div id="2102e75d" class="cell" data-execution_count="2">
<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">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;">readRDS</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"reg_data.rds"</span>)</span>
<span id="cb3-2">X <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>X; true_beta <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>true_beta</span>
<span id="cb3-3">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;">nrow</span>(X); 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;">ncol</span>(X)</span>
<span id="cb3-4"></span>
<span id="cb3-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;">1</span>)</span>
<span id="cb3-6">B <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;">300</span></span>
<span id="cb3-7">ols_coefs <span class="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;">NA</span>, B, p)</span>
<span id="cb3-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (b <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>(B)) {</span>
<span id="cb3-9">  y_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.vector</span>(X <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> true_beta <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;">rnorm</span>(n, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</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;"># fresh noise draw, same X</span></span>
<span id="cb3-10">  ols_coefs[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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lm</span>(y_b <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> X <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="cb3-11">}</span>
<span id="cb3-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(ols_coefs) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(X)</span>
<span id="cb3-13"></span>
<span id="cb3-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Standard deviation of OLS estimates for each predictor:</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>)</span>
<span id="cb3-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</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;">apply</span>(ols_coefs, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, sd), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Standard deviation of OLS estimates for each predictor:
  X1   X2   X3   X4   X5   X6   X7   X8   X9  X10 
0.49 0.51 0.46 0.52 0.52 0.52 0.55 0.52 0.21 0.22 </code></pre>
</div>
</div>
<p>The correlated-block predictors (X1–X8) have roughly double the standard deviation of the independent ones (X9, X10) — 0.5 versus 0.2 — purely because of correlation, not because they’re individually less informative. OLS is unbiased here (the boxes are centered near the true values), but “unbiased and wildly variable” is not a comforting property when you’re trying to trust a specific estimate from a specific sample.</p>
<p>Regularization trades away a little of that unbiasedness in exchange for a large reduction in variance — a good trade whenever variance is the bigger problem, which it usually is with correlated or high-dimensional predictors.</p>
</section>
</section>
<section id="ridge-regression-shrinking-with-an-l2-penalty" class="level1" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Ridge Regression: Shrinking with an L2 Penalty</h1>
<blockquote class="blockquote">
<p><strong>What does ridge regression actually change about the objective function?</strong> It adds a penalty proportional to the <em>squared</em> size of the coefficients, so the optimizer is rewarded for keeping them small, not just for fitting the training data.</p>
</blockquote>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%5Cbeta_%7B%5Ctext%7Bridge%7D%7D%20=%20%5Carg%5Cmin_%5Cbeta%20%5Cleft%5C%7B%20%5Csum_%7Bi=1%7D%5En%20(y_i%20-%20x_i%5E%5Ctop%5Cbeta)%5E2%20+%20%5Clambda%5Csum_%7Bj=1%7D%5Ep%20%5Cbeta_j%5E2%20%5Cright%5C%7D%0A"></p>
<p><img src="https://latex.codecogs.com/png.latex?%5Clambda%20%5Cge%200"> controls the strength of the penalty: <img src="https://latex.codecogs.com/png.latex?%5Clambda=0"> recovers plain OLS, and as <img src="https://latex.codecogs.com/png.latex?%5Clambda%5Cto%5Cinfty"> every coefficient is forced toward zero. Because the penalty is smooth and quadratic, this objective has a closed-form solution:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%5Cbeta_%7B%5Ctext%7Bridge%7D%7D%20=%20(X%5E%5Ctop%20X%20+%20%5Clambda%20I)%5E%7B-1%7DX%5E%5Ctop%20y%0A"></p>
<p>Compare this to the OLS solution, <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_%7B%5Ctext%7BOLS%7D%7D%20=%20(X%5E%5Ctop%20X)%5E%7B-1%7DX%5E%5Ctop%20y">: ridge simply adds <img src="https://latex.codecogs.com/png.latex?%5Clambda"> to the diagonal of <img src="https://latex.codecogs.com/png.latex?X%5E%5Ctop%20X"> before inverting. This is precisely the fix for the numerical instability that correlated predictors cause — <img src="https://latex.codecogs.com/png.latex?X%5E%5Ctop%20X"> becomes close to singular (nearly non-invertible) when columns are highly correlated, and adding <img src="https://latex.codecogs.com/png.latex?%5Clambda%20I"> keeps it comfortably invertible (this is why ridge is sometimes called Tikhonov regularization, its original name in the applied-math literature).</p>
<div id="cd4bcb92" class="cell" data-execution_count="3">
<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">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;">readRDS</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"reg_data.rds"</span>)</span>
<span id="cb5-2">X <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>X; 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; true_beta <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>true_beta</span>
<span id="cb5-3">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;">nrow</span>(X); 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;">ncol</span>(X)</span>
<span id="cb5-4"></span>
<span id="cb5-5">ridge_fit <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, y, lambda) {</span>
<span id="cb5-6">  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;">ncol</span>(X)</span>
<span id="cb5-7">  <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;">t</span>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> X <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lambda <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;">diag</span>(p), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> y)</span>
<span id="cb5-8">}</span>
<span id="cb5-9"></span>
<span id="cb5-10">lambda_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.01</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;">500</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;">60</span>))</span>
<span id="cb5-11">ridge_path <span class="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>(lambda_grid, <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;">ridge_fit</span>(X, y, l)))</span>
<span id="cb5-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(ridge_path) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(X)</span>
<span id="cb5-13"></span>
<span id="cb5-14"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Sanity check against the OLS solution as lambda -&gt; 0</span></span>
<span id="cb5-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ridge at lambda~0     :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(ridge_path[<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="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>)</span>
<span id="cb5-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OLS (lm)              :"</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;">coef</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> X <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;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb5-17"></span>
<span id="cb5-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">saveRDS</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;">lambda_grid =</span> lambda_grid, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ridge_path =</span> ridge_path), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ridge_path.rds"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Ridge at lambda~0     : 2.808 -0.636 0.445 0.293 -1.273 -0.078 -0.88 0.226 1.832 0.307 
OLS (lm)              : 2.809 -0.636 0.445 0.293 -1.273 -0.078 -0.88 0.226 1.832 0.307 </code></pre>
</div>
</div>
<p>As it must: with <img src="https://latex.codecogs.com/png.latex?%5Clambda"> essentially at zero, ridge and OLS agree to three decimal places. Now trace out the full path as <img src="https://latex.codecogs.com/png.latex?%5Clambda"> grows.</p>
<div id="299f225e" class="cell" data-execution_count="4">
<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">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;">ncol</span>(X)</span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(lambda_grid), ridge_path, <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;">"l"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</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;">lwd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb7-3">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rainbow</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">end =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.85</span>),</span>
<span id="cb7-4">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expression</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(lambda)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expression</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hat</span>(beta)),</span>
<span id="cb7-5">        <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;">"Ridge coefficient paths"</span>)</span>
<span id="cb7-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">h =</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;">lty =</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;">col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey40"</span>)</span>
<span id="cb7-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">legend</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"topright"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(X), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rainbow</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">end =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.85</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</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;">lwd =</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;">cex =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/ridge_lasso/ridge_lasso_tutorial_files/figure-html/cell-5-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Every coefficient shrinks smoothly and continuously toward zero as <img src="https://latex.codecogs.com/png.latex?%5Clambda"> increases, but none of them ever actually <em>reach</em> zero (except in the limit). That single observation — smooth shrinkage, never exactly zero — is the entire practical difference between ridge and lasso, and it comes directly from using a squared penalty instead of an absolute one. We’ll see exactly why in the geometry section below.</p>
</section>
<section id="lasso-an-l1-penalty-and-the-sparsity-it-creates" class="level1" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> Lasso: An L1 Penalty and the Sparsity It Creates</h1>
<p>Lasso (Tibshirani, 1996) replaces the squared penalty with an absolute one:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%5Cbeta_%7B%5Ctext%7Blasso%7D%7D%20=%20%5Carg%5Cmin_%5Cbeta%20%5Cleft%5C%7B%20%5Csum_%7Bi=1%7D%5En%20(y_i%20-%20x_i%5E%5Ctop%5Cbeta)%5E2%20+%20%5Clambda%5Csum_%7Bj=1%7D%5Ep%20%7C%5Cbeta_j%7C%20%5Cright%5C%7D%0A"></p>
<blockquote class="blockquote">
<p><strong>Why doesn’t this have a closed-form solution the way ridge does?</strong> The absolute value function isn’t differentiable at zero. Calculus-based closed forms rely on setting a smooth derivative to zero everywhere; lasso’s objective has a kink exactly where the interesting behavior (a coefficient becoming zero) happens.</p>
</blockquote>
<p>Instead, lasso is solved iteratively. <strong>Coordinate descent</strong> (Friedman, Hastie &amp; Tibshirani, 2010) optimizes one coefficient at a time, holding all others fixed, and cycles through all predictors repeatedly until nothing changes. Fixing every <img src="https://latex.codecogs.com/png.latex?%5Cbeta_k"> for <img src="https://latex.codecogs.com/png.latex?k%20%5Cne%20j">, the one-dimensional update for <img src="https://latex.codecogs.com/png.latex?%5Cbeta_j"> turns out to be a simple <strong>soft-thresholding</strong> operation:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%5Cbeta_j%20%5Cleftarrow%20%5Cfrac%7BS%5Cleft(%5Csum_i%20x_%7Bij%7D%5Cleft(y_i%20-%20%5Csum_%7Bk%5Cne%20j%7D%20x_%7Bik%7D%5Cbeta_k%5Cright),%5C;%20n%5Clambda/2%5Cright)%7D%7B%5Csum_i%20x_%7Bij%7D%5E2%7D,%20%5Cqquad%20S(z,%5Cgamma)%20=%20%5Ctext%7Bsign%7D(z)%5Cmax(%7Cz%7C-%5Cgamma,%5C%200)%0A"></p>
<p><img src="https://latex.codecogs.com/png.latex?S"> shrinks its input toward zero by <img src="https://latex.codecogs.com/png.latex?%5Cgamma">, and clips it to exactly zero if the input wasn’t larger than <img src="https://latex.codecogs.com/png.latex?%5Cgamma"> to begin with. That clipping-to-exactly-zero step is where lasso’s sparsity comes from — it’s baked directly into the per-coordinate update rule.</p>
<div id="bb231478" class="cell" data-execution_count="5">
<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">soft_threshold <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, gamma) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sign</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;">pmax</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(z) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> gamma, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb8-2"></span>
<span id="cb8-3">lasso_fit <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, y, lambda, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tol =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-8</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max_iter =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>) {</span>
<span id="cb8-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;">ncol</span>(X); 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;">nrow</span>(X)</span>
<span id="cb8-5">  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;">rep</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, p)</span>
<span id="cb8-6">  Xy <span class="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>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> y</span>
<span id="cb8-7">  XtX <span class="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>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> X</span>
<span id="cb8-8"></span>
<span id="cb8-9">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (iter <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>(max_iter)) {</span>
<span id="cb8-10">    beta_old <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> beta</span>
<span id="cb8-11">    <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_len</span>(p)) {</span>
<span id="cb8-12">      r_j <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> Xy[j] <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>(XtX[j, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>j] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> beta[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>j])</span>
<span id="cb8-13">      beta[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;">soft_threshold</span>(r_j, n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</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;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> XtX[j, j]</span>
<span id="cb8-14">    }</span>
<span id="cb8-15">    <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;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(beta <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> beta_old)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> tol) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span></span>
<span id="cb8-16">  }</span>
<span id="cb8-17">  beta</span>
<span id="cb8-18">}</span>
<span id="cb8-19"></span>
<span id="cb8-20"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Verify the coordinate-descent update against the univariate closed form:</span></span>
<span id="cb8-21"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## for a single predictor (no correlated neighbours), lasso reduces to soft-</span></span>
<span id="cb8-22"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## thresholding the OLS coefficient directly.</span></span>
<span id="cb8-23">x1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> X[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb8-24">beta_ols_uni <span class="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>(x1 <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;">sum</span>(x1<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-25">lambda_test <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="cb8-26">beta_lasso_uni <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">soft_threshold</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> y), n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lambda_test <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>(x1<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-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Univariate OLS beta          :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(beta_ols_uni, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Univariate soft-thresholded  :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(beta_lasso_uni, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</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;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-29"></span>
<span id="cb8-30">lambda_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.005</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;">3</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;">60</span>))</span>
<span id="cb8-31">lasso_path <span class="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>(lambda_grid, <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;">lasso_fit</span>(X, y, l)))</span>
<span id="cb8-32"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(lasso_path) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(X)</span>
<span id="cb8-33"></span>
<span id="cb8-34"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lasso at lambda~0 (should match OLS):"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(lasso_path[<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="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>)</span>
<span id="cb8-35"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OLS (lm)                             :"</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;">coef</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> X <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;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-36"></span>
<span id="cb8-37"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">saveRDS</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;">lambda_grid =</span> lambda_grid, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lasso_path =</span> lasso_path), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lasso_path.rds"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Univariate OLS beta          : 2.9352 
Univariate soft-thresholded  : 2.7844 

Lasso at lambda~0 (should match OLS): 2.8 -0.614 0.434 0.289 -1.267 -0.067 -0.868 0.199 1.831 0.305 
OLS (lm)                             : 2.809 -0.636 0.445 0.293 -1.273 -0.078 -0.88 0.226 1.832 0.307 </code></pre>
</div>
</div>
<p>Both checks hold: the univariate soft-thresholded estimate is a shrunken version of the univariate OLS estimate (2.78 vs.&nbsp;2.94, exactly what soft-thresholding by a positive amount should do), and the full multivariate lasso path recovers OLS almost exactly as <img src="https://latex.codecogs.com/png.latex?%5Clambda%5Cto0">. Now the path itself:</p>
<div id="70f8107b" class="cell" data-execution_count="6">
<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">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;">ncol</span>(X)</span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(lambda_grid), lasso_path, <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;">"l"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</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;">lwd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb10-3">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rainbow</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">end =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.85</span>),</span>
<span id="cb10-4">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expression</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(lambda)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expression</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hat</span>(beta)),</span>
<span id="cb10-5">        <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;">"Lasso coefficient paths"</span>)</span>
<span id="cb10-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">h =</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;">lty =</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;">col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey40"</span>)</span>
<span id="cb10-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">legend</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"topright"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(X), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rainbow</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">end =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.85</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</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;">lwd =</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;">cex =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/ridge_lasso/ridge_lasso_tutorial_files/figure-html/cell-7-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<p>This is the signature lasso picture: coefficients don’t just shrink, they drop to <em>exactly</em> zero, one by one, in a staircase pattern as <img src="https://latex.codecogs.com/png.latex?%5Clambda"> increases. Compare this directly to the ridge path above — same data, same <img src="https://latex.codecogs.com/png.latex?%5Clambda"> range in spirit, completely different qualitative behavior.</p>
</section>
<section id="the-geometry-behind-why-lasso-zeroes-out-coefficients" class="level1" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> The Geometry Behind Why Lasso Zeroes Out Coefficients</h1>
<p>Both penalized objectives have an equivalent “constrained optimization” formulation: minimize the residual sum of squares subject to a budget on the total penalty. For lasso, the budget is on <img src="https://latex.codecogs.com/png.latex?%5Csum%7C%5Cbeta_j%7C"> — geometrically, a <strong>diamond</strong> (in two dimensions) centered at the origin. For ridge, the budget is on <img src="https://latex.codecogs.com/png.latex?%5Csum%5Cbeta_j%5E2"> — a <strong>circle</strong>.</p>
<blockquote class="blockquote">
<p><strong>Why does a diamond produce exact zeros but a circle doesn’t?</strong> Picture the OLS solution as the center of a series of concentric ellipses (contours of equal residual sum of squares — every point on the same ellipse fits the training data equally well). The penalized solution is wherever the <em>smallest</em> ellipse first touches the constraint boundary. A diamond has corners sitting exactly on the coordinate axes; an ellipse is disproportionately likely to first touch the diamond at one of those corners, which is precisely the point where one coordinate is zero. A circle has no corners anywhere, so there’s nothing to make touching at an axis special.</p>
</blockquote>
<p>We can make this exact rather than hand-wavy, using two genuinely correlated predictors and finding where an actual RSS contour touches an actual diamond and an actual circle.</p>
<div id="378be40b" class="cell" data-execution_count="7">
<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"><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="cb11-2">n <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="cb11-3">rho <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.6</span></span>
<span id="cb11-4">Sigma2 <span class="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;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, rho, rho, <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;">2</span>)</span>
<span id="cb11-5">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;">chol</span>(Sigma2)</span>
<span id="cb11-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;">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> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb11-7">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;">scale</span>(Z <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> L)</span>
<span id="cb11-8">true_beta2 <span class="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;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.4</span>)</span>
<span id="cb11-9">y2 <span class="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.vector</span>(X2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> true_beta2 <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;">rnorm</span>(n, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>))</span>
<span id="cb11-10"></span>
<span id="cb11-11">beta_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;">as.vector</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;">t</span>(X2) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> X2, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(X2) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> y2))</span>
<span id="cb11-12">XtX <span class="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>(X2) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> X2</span>
<span id="cb11-13">rss_val <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>(b) { d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> b <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> beta_hat; <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;">t</span>(d) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> XtX <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> d) }</span>
<span id="cb11-14"></span>
<span id="cb11-15">t_budget <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 tight penalty budget, so the constraint clearly binds</span></span>
<span id="cb11-16"></span>
<span id="cb11-17"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Grid-search along each edge of the L1 diamond for the true RSS-minimizing point</span></span>
<span id="cb11-18">diamond_vertices <span class="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;">c</span>(t_budget, <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;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, t_budget), <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>t_budget, <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;">c</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>t_budget), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(t_budget, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>))</span>
<span id="cb11-19">s_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;">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="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;">2000</span>)</span>
<span id="cb11-20">best_rss_l1 <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;">Inf</span>; best_pt_l1 <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;">NULL</span></span>
<span id="cb11-21"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (e <span class="cf" 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="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) {</span>
<span id="cb11-22">  v1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> diamond_vertices[e, ]; v2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> diamond_vertices[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>, ]</span>
<span id="cb11-23">  pts <span class="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>(s_grid, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) (<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> s) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> v1 <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> v2))</span>
<span id="cb11-24">  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;">apply</span>(pts, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, rss_val)</span>
<span id="cb11-25">  <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>(r) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> best_rss_l1) { best_rss_l1 <span class="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>(r); best_pt_l1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pts[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.min</span>(r), ] }</span>
<span id="cb11-26">}</span>
<span id="cb11-27"></span>
<span id="cb11-28"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Grid-search around the L2 circle for the true RSS-minimizing point</span></span>
<span id="cb11-29">theta_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;">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;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> pi, <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;">4000</span>)</span>
<span id="cb11-30">circle_pts <span class="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>(t_budget <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;">cos</span>(theta_grid), t_budget <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;">sin</span>(theta_grid))</span>
<span id="cb11-31">r_circle <span class="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>(circle_pts, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, rss_val)</span>
<span id="cb11-32">best_pt_l2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> circle_pts[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.min</span>(r_circle), ]</span>
<span id="cb11-33"></span>
<span id="cb11-34"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Diamond (lasso) touching point:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(best_pt_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb11-35">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-- exactly zero on one axis:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(best_pt_l1) <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-6</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb11-36"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Circle (ridge) touching point :"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(best_pt_l2, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Diamond (lasso) touching point: 0.5 0 -- exactly zero on one axis: TRUE 
Circle (ridge) touching point : 0.369 0.337 </code></pre>
</div>
</div>
<p>The diamond-constrained solution lands exactly at a corner: <img src="https://latex.codecogs.com/png.latex?%5Cbeta_2%20=%200">, not approximately, exactly. The circle-constrained solution lands at a generic point on the boundary with both coordinates nonzero. Same data, same RSS ellipses, same size budget — the only thing that changed is the shape of the constraint region, and that alone accounts for the sparsity.</p>
</section>
<section id="choosing-lambda-by-cross-validation" class="level1" data-number="5">
<h1 data-number="5"><span class="header-section-number">5</span> Choosing <img src="https://latex.codecogs.com/png.latex?%5Clambda"> by Cross-Validation</h1>
<p>Neither the coefficient path nor the geometry tells you which <img src="https://latex.codecogs.com/png.latex?%5Clambda"> to actually use. That’s chosen empirically, by holding out folds of data and measuring prediction error.</p>
<div id="0a4f1ca0" class="cell" data-execution_count="8">
<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">ridge_fit <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, y, lambda) <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;">t</span>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> X <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lambda <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;">diag</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(X)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(X) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> y)</span>
<span id="cb13-2"></span>
<span id="cb13-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;">99</span>)</span>
<span id="cb13-4">K <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="cb13-5">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;">nrow</span>(X)</span>
<span id="cb13-6">folds <span class="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;">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>K, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> n))</span>
<span id="cb13-7"></span>
<span id="cb13-8">cv_error <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>(fit_fn, lambda_grid) {</span>
<span id="cb13-9">  errs <span class="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;">NA</span>, K, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(lambda_grid))</span>
<span id="cb13-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> <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>
<span id="cb13-11">    train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> folds <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> k; test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> folds <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k</span>
<span id="cb13-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (li <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>(lambda_grid)) {</span>
<span id="cb13-13">      beta_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;">fit_fn</span>(X[train, , <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>], y[train], lambda_grid[li])</span>
<span id="cb13-14">      pred <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> X[test, , drop <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 class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> beta_k</span>
<span id="cb13-15">      errs[k, li] <span class="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>((y[test] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> pred)<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="cb13-16">    }</span>
<span id="cb13-17">  }</span>
<span id="cb13-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colMeans</span>(errs)</span>
<span id="cb13-19">}</span>
<span id="cb13-20"></span>
<span id="cb13-21">ridge_lambda_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.01</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;">500</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;">40</span>))</span>
<span id="cb13-22">lasso_lambda_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.005</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;">3</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;">40</span>))</span>
<span id="cb13-23"></span>
<span id="cb13-24">ridge_cv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cv_error</span>(ridge_fit, ridge_lambda_grid)</span>
<span id="cb13-25">lasso_cv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cv_error</span>(lasso_fit, lasso_lambda_grid)</span>
<span id="cb13-26"></span>
<span id="cb13-27">ridge_lambda_min <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ridge_lambda_grid[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.min</span>(ridge_cv)]</span>
<span id="cb13-28">lasso_lambda_min <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lasso_lambda_grid[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.min</span>(lasso_cv)]</span>
<span id="cb13-29"></span>
<span id="cb13-30"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ridge lambda.min:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(ridge_lambda_min, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" CV MSE:"</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>(ridge_cv), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb13-31"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lasso lambda.min:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(lasso_lambda_min, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" CV MSE:"</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>(lasso_cv), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb13-32"></span>
<span id="cb13-33"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">saveRDS</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;">ridge_lambda_grid =</span> ridge_lambda_grid, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ridge_cv =</span> ridge_cv,</span>
<span id="cb13-34">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lasso_lambda_grid =</span> lasso_lambda_grid, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lasso_cv =</span> lasso_cv,</span>
<span id="cb13-35">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ridge_lambda_min =</span> ridge_lambda_min, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lasso_lambda_min =</span> lasso_lambda_min),</span>
<span id="cb13-36">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cv_results.rds"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Ridge lambda.min: 7.792  CV MSE: 9.491 
Lasso lambda.min: 0.185  CV MSE: 9.45 </code></pre>
</div>
</div>
<p>Both curves have the same characteristic shape: error is high when <img src="https://latex.codecogs.com/png.latex?%5Clambda"> is too small (overfitting; barely different from OLS) or too large (underfitting; everything shrunk toward a useless zero model), with a minimum somewhere in between. Here ridge and lasso land on almost identical best-case prediction error (9.49 vs.&nbsp;9.45) on this data — which won’t always be true, but is a reasonable outcome when, as here, most of the true signal is concentrated in a few predictors alongside genuine noise.</p>
</section>
<section id="the-bias-variance-tradeoff-made-concrete" class="level1" data-number="6">
<h1 data-number="6"><span class="header-section-number">6</span> The Bias-Variance Tradeoff, Made Concrete</h1>
<p>Regularization is often described as “trading bias for variance.” That’s not just a slogan — we can measure both quantities directly by repeatedly simulating fresh data, fitting ridge at each <img src="https://latex.codecogs.com/png.latex?%5Clambda">, and tracking how far the average prediction is from the truth (bias) versus how much predictions bounce around across simulations (variance).</p>
<div id="26113f3a" class="cell" data-execution_count="9">
<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">true_beta <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>true_beta</span>
<span id="cb15-2">lambda_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.01</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;">500</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;">30</span>))</span>
<span id="cb15-3"></span>
<span id="cb15-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;">5</span>)</span>
<span id="cb15-5">B <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="cb15-6">x_new <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> X[<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a fixed held-out "test" design to evaluate prediction error on</span></span>
<span id="cb15-7">true_signal <span class="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.vector</span>(x_new <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> true_beta)</span>
<span id="cb15-8"></span>
<span id="cb15-9">bias2 <span class="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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(lambda_grid))</span>
<span id="cb15-10">variance <span class="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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(lambda_grid))</span>
<span id="cb15-11">mse <span class="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>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(lambda_grid))</span>
<span id="cb15-12"></span>
<span id="cb15-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (li <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>(lambda_grid)) {</span>
<span id="cb15-14">  preds <span class="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;">NA</span>, B, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(x_new))</span>
<span id="cb15-15">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (b <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>(B)) {</span>
<span id="cb15-16">    y_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.vector</span>(X <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> true_beta <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;">rnorm</span>(n, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb15-17">    beta_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;">ridge_fit</span>(X, y_b, lambda_grid[li])</span>
<span id="cb15-18">    preds[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.vector</span>(x_new <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> beta_b)</span>
<span id="cb15-19">  }</span>
<span id="cb15-20">  mean_pred <span class="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>(preds)</span>
<span id="cb15-21">  bias2[li]    <span class="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>((mean_pred <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> true_signal)<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="cb15-22">  variance[li] <span class="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;">apply</span>(preds, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var))</span>
<span id="cb15-23">  mse[li]      <span class="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>((preds <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;">matrix</span>(true_signal, B, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(true_signal), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">byrow =</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 class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb15-24">}</span>
<span id="cb15-25"></span>
<span id="cb15-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bias^2 range   :"</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;">range</span>(bias2), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb15-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Variance range :"</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;">range</span>(variance), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb15-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lambda at min total MSE:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(lambda_grid[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.min</span>(mse)], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</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;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Bias^2 range   : 0.002 6.827 
Variance range : 0.059 0.626 
lambda at min total MSE: 0.198 </code></pre>
</div>
</div>
<p>At small <img src="https://latex.codecogs.com/png.latex?%5Clambda">, bias is negligible but variance dominates total error. As <img src="https://latex.codecogs.com/png.latex?%5Clambda"> grows, variance drops sharply while bias climbs slowly at first, then steeply. The total error curve (black) is the sum of the two, and its minimum sits well away from <img src="https://latex.codecogs.com/png.latex?%5Clambda=0"> — meaning the “unbiased” OLS solution is <em>not</em> the one with the lowest expected prediction error. A little deliberate bias buys a large variance reduction, right up until the penalty gets so strong that bias takes over.</p>
</section>
<section id="ridge-vs.-lasso-side-by-side" class="level1" data-number="7">
<h1 data-number="7"><span class="header-section-number">7</span> Ridge vs.&nbsp;Lasso, Side by Side</h1>
<p>Putting it all together: fit OLS, ridge (at its CV-selected <img src="https://latex.codecogs.com/png.latex?%5Clambda">), and lasso (at its CV-selected <img src="https://latex.codecogs.com/png.latex?%5Clambda">) on the same data, and compare all three against the true coefficients.</p>
<div id="e015ca9d" class="cell" data-execution_count="10">
<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">cvres <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">readRDS</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cv_results.rds"</span>)</span>
<span id="cb17-2"></span>
<span id="cb17-3">beta_ols   <span class="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>(<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> X <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="cb17-4">beta_ridge <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ridge_fit</span>(X, y, cvres<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ridge_lambda_min)</span>
<span id="cb17-5">beta_lasso <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lasso_fit</span>(X, y, cvres<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lasso_lambda_min)</span>
<span id="cb17-6"></span>
<span id="cb17-7">compare <span class="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>(true_beta, beta_ols, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(beta_ridge), beta_lasso)</span>
<span id="cb17-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(compare) <span class="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;">"True"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OLS"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ridge (CV)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lasso (CV)"</span>)</span>
<span id="cb17-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(compare) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(X)</span>
<span id="cb17-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(compare, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>             X1    X2   X3   X4    X5    X6    X7   X8   X9  X10
True       3.00  0.00 0.00 0.00 -2.00  0.00  0.00 0.00 1.50 0.00
OLS        2.81 -0.64 0.45 0.29 -1.27 -0.08 -0.88 0.23 1.83 0.31
Ridge (CV) 2.39 -0.37 0.47 0.39 -1.13 -0.17 -0.77 0.11 1.76 0.31
Lasso (CV) 2.55  0.00 0.20 0.10 -1.18  0.00 -0.71 0.00 1.77 0.23</code></pre>
</div>
</div>
<p>Lasso sets X2, X6, and X8 to exactly zero — three of the seven truly-null predictors — while ridge shrinks every coefficient toward zero without eliminating any of them. Neither recovers the true model exactly (the correlated “twin” predictors within each block make that a genuinely hard problem), but lasso’s sparsity gives a noticeably more interpretable result here, at comparable predictive accuracy to ridge.</p>
</section>
<section id="when-to-reach-for-which" class="level1" data-number="8">
<h1 data-number="8"><span class="header-section-number">8</span> When to Reach for Which</h1>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Situation</th>
<th>Better choice</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>You believe most predictors have <em>some</em> small effect (a “dense” true model)</td>
<td>Ridge</td>
</tr>
<tr class="even">
<td>You believe only a handful of predictors truly matter (a “sparse” true model)</td>
<td>Lasso</td>
</tr>
<tr class="odd">
<td>Predictors come in tightly correlated groups, and you want to keep all of them</td>
<td>Ridge (spreads weight across the group rather than picking one arbitrarily)</td>
</tr>
<tr class="even">
<td>You want automatic variable selection alongside estimation</td>
<td>Lasso</td>
</tr>
<tr class="odd">
<td><img src="https://latex.codecogs.com/png.latex?p%20%3E%20n"> (more predictors than observations)</td>
<td>Both work; lasso additionally gives a sparse, interpretable model</td>
</tr>
<tr class="even">
<td>You want the properties of both</td>
<td>Elastic net — <img src="https://latex.codecogs.com/png.latex?%5Clambda%5Cleft%5B(1-%5Calpha)%5Csum%5Cbeta_j%5E2/2%20+%20%5Calpha%5Csum%7C%5Cbeta_j%7C%5Cright%5D">, tuning <img src="https://latex.codecogs.com/png.latex?%5Calpha%20%5Cin%20%5B0,1%5D"> between them (Zou &amp; Hastie, 2005)</td>
</tr>
</tbody>
</table>
<p>One caveat about lasso and correlated predictors worth internalizing from the geometry section: when two predictors are highly correlated, lasso tends to arbitrarily pick one and zero out the other, rather than splitting credit between them the way ridge does. That’s a feature if you want a small, interpretable model, and a liability if the identity of <em>which</em> correlated predictor gets picked matters for your interpretation.</p>
</section>
<section id="summary" class="level1" data-number="9">
<h1 data-number="9"><span class="header-section-number">9</span> Summary</h1>
<ol type="1">
<li>Both ridge and lasso add a penalty on coefficient size to the OLS objective, trading a small amount of bias for a often much larger reduction in variance.</li>
<li>Ridge’s squared (L2) penalty has a closed-form solution and shrinks every coefficient smoothly, never to exactly zero.</li>
<li>Lasso’s absolute-value (L1) penalty has no closed form, requires an iterative solver like coordinate descent, and produces exact sparsity — some coefficients become precisely zero.</li>
<li>The sparsity difference is entirely geometric: a diamond-shaped constraint region has corners on the coordinate axes; a circular one doesn’t.</li>
<li>The regularization strength <img src="https://latex.codecogs.com/png.latex?%5Clambda"> is chosen empirically via cross-validation, by directly measuring which value minimizes out-of-sample prediction error.</li>
</ol>
</section>
<section id="references" class="level1" data-number="10">
<h1 data-number="10"><span class="header-section-number">10</span> References</h1>
<ul>
<li>Hoerl, A. E. &amp; Kennard, R. W. (1970). Ridge regression: biased estimation for nonorthogonal problems. <em>Technometrics</em>, 12, 55–67.</li>
<li>Tibshirani, R. (1996). Regression shrinkage and selection via the lasso. <em>Journal of the Royal Statistical Society: Series B</em>, 58, 267–288.</li>
<li>Zou, H. &amp; Hastie, T. (2005). Regularization and variable selection via the elastic net. <em>Journal of the Royal Statistical Society: Series B</em>, 67, 301–320.</li>
<li>Friedman, J., Hastie, T. &amp; Tibshirani, R. (2010). Regularization paths for generalized linear models via coordinate descent. <em>Journal of Statistical Software</em>, 33, 1.</li>
<li>Hastie, T., Tibshirani, R. &amp; Friedman, J. (2009). <em>The Elements of Statistical Learning</em> (2nd ed.). Springer.</li>
</ul>


</section>

 ]]></description>
  <guid>https://bntechie.github.io/tutorials/ridge_lasso/ridge_lasso_tutorial.html</guid>
  <pubDate>Tue, 09 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Polygenic Risk Scores (PRS): From GWAS to Genetic Prediction</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/PRS/Polygenic_Risk_Scores.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/PRS/images/prs-pipeline.svg" alt="Pipeline diagram showing GWAS summary statistics flowing through a PRS method (C+PT, SBayesR, or SBayesRC) into an individual polygenic risk score, visualized as a distribution split into low, average, and high risk groups" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>The whole tutorial in one picture: millions of small GWAS effects, combined by a PRS method, collapse into a single number per person – which is only useful once you can place that person in a risk distribution.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">GWAS</span> <span class="tag">PRS</span> <span class="tag">SBayesRC</span> <span class="tag">PLINK</span></p>
</div>
<section id="why-polygenic-risk-scores" class="level2" data-number="0.1">
<h2 data-number="0.1" class="anchored" data-anchor-id="why-polygenic-risk-scores"><span class="header-section-number">0.1</span> Why Polygenic Risk Scores?</h2>
<p>Mendelian diseases (Huntington’s, cystic fibrosis, sickle cell anemia) are driven by mutations in a single gene. Most common diseases aren’t — height, BMI, coronary artery disease, schizophrenia, and depression are each influenced by thousands of variants, each with a tiny individual effect (<strong>polygenicity</strong>). No single SNP is informative enough to predict risk on its own, which raises the question: how do we combine thousands of tiny genetic effects into a useful predictor? A <strong>Polygenic Risk Score (PRS)</strong> — also called a Polygenic Score (PGS) — is the answer: a weighted sum of genetic variants across the genome, condensing an individual’s inherited predisposition into a single number.</p>
</section>
<section id="what-is-a-prs" class="level2" data-number="0.2">
<h2 data-number="0.2" class="anchored" data-anchor-id="what-is-a-prs"><span class="header-section-number">0.2</span> What Is a PRS?</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPRS%7D_i%20=%20%5Csum_%7Bj=1%7D%5E%7Bm%7D%20%5Chat%5Cbeta_j%5C,%20x_%7Bij%7D"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?i"> indexes the individual, <img src="https://latex.codecogs.com/png.latex?j"> indexes the SNP, <img src="https://latex.codecogs.com/png.latex?m"> is the number of SNPs, <img src="https://latex.codecogs.com/png.latex?x_%7Bij%7D%20%5Cin%20%5C%7B0,1,2%5C%7D"> is the individual’s risk-allele count at SNP <img src="https://latex.codecogs.com/png.latex?j">, and <img src="https://latex.codecogs.com/png.latex?%5Chat%5Cbeta_j"> is that SNP’s estimated effect size — usually taken directly from GWAS summary statistics. Positive <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> increases risk; negative <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> decreases it.</p>
<p><strong>Worked example.</strong> Given effects <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7Brs1%7D=0.05">, <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7Brs2%7D=0.02">, <img src="https://latex.codecogs.com/png.latex?%5Cbeta_%7Brs3%7D=-0.03">, and an individual with genotype counts 2, 1, 0:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPRS%7D%20=%20(0.05)(2)%20+%20(0.02)(1)%20+%20(-0.03)(0)%20=%200.12"></p>
</section>
<section id="why-prs-works-despite-tiny-often-non-causal-snps" class="level2" data-number="0.3">
<h2 data-number="0.3" class="anchored" data-anchor-id="why-prs-works-despite-tiny-often-non-causal-snps"><span class="header-section-number">0.3</span> Why PRS Works Despite Tiny, Often Non-Causal SNPs</h2>
<p>Most SNPs used in a PRS aren’t themselves causal — they still improve prediction because of <strong>Linkage Disequilibrium (LD)</strong>, the tendency of nearby SNPs to be co-inherited. Even without observing the true causal SNP directly, an observed SNP correlated with it still carries predictive information. This is the same principle underlying GWAS itself.</p>
<p><strong>Analogy: a genetic credit score.</strong> Just as a bank doesn’t judge creditworthiness from one transaction but aggregates many small signals, a PRS aggregates many small genetic signals into one composite score.</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BDiscovery%20GWAS%7D%20%5Crightarrow%20%5Ctext%7BEffect%20Sizes%7D%20%5Crightarrow%20%5Ctext%7BTarget%20Genotypes%7D%20%5Crightarrow%20%5Ctext%7BPRS%7D"></p>
<p>The <strong>discovery dataset</strong> produces GWAS effect sizes; the <strong>target dataset</strong> provides the genotypes (<img src="https://latex.codecogs.com/png.latex?x_%7Bij%7D">) of new individuals the score will be applied to. The GWAS effect sizes are simply applied to the target genotypes using the PRS formula above.</p>
</section>
<section id="what-a-prs-does-and-doesnt-mean" class="level2" data-number="0.4">
<h2 data-number="0.4" class="anchored" data-anchor-id="what-a-prs-does-and-doesnt-mean"><span class="header-section-number">0.4</span> What a PRS Does and Doesn’t Mean</h2>
<p>A PRS is <strong>not</strong> a diagnosis and does not directly measure disease. It represents relative inherited genetic predisposition compared with others in the population — environmental factors still play a major role in whether disease actually develops.</p>
<p><strong>Applications:</strong> cardiovascular medicine (identifying individuals with elevated genetic risk for early intervention), and more broadly across common disease research.</p>
<p><strong>Limitations:</strong> prediction accuracy is fundamentally capped by the trait’s heritability, GWAS discovery sample size, and how well the discovery population’s ancestry matches the target population (Part 9 covers this in depth).</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> A PRS is a weighted sum of genotype counts and GWAS effect sizes across many SNPs. It works even for non-causal SNPs because of LD with true causal variants. A PRS reflects relative genetic predisposition, not a diagnosis, and its accuracy is bounded by heritability and by how well discovery and target populations match.</p>
</blockquote>
</section>
<section id="evaluating-polygenic-risk-scores" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Evaluating Polygenic Risk Scores</h1>
<p>A PRS is only useful if it actually predicts the trait — so how well it predicts must be measured rigorously, on held-out data, using metrics that suit the outcome type.</p>
<section id="quantitative-traits-r²-and-incremental-r²" class="level2" data-number="1.1">
<h2 data-number="1.1" class="anchored" data-anchor-id="quantitative-traits-r²-and-incremental-r²"><span class="header-section-number">1.1</span> Quantitative Traits: R² and Incremental R²</h2>
<p>For continuous traits (height, BMI, LDL), the standard metric is <strong>R²</strong>, the proportion of phenotypic variance explained. Fit a <strong>null model</strong> with covariates only, then a <strong>full model</strong> adding the PRS:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BNull:%20Phenotype%7D%20%5Csim%20%5Ctext%7BAge%7D%20+%20%5Ctext%7BSex%7D%20+%20%5Ctext%7BPCs%7D"> <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BFull:%20Phenotype%7D%20%5Csim%20%5Ctext%7BAge%7D%20+%20%5Ctext%7BSex%7D%20+%20%5Ctext%7BPCs%7D%20+%20%5Ctext%7BPRS%7D"></p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BIncremental%20%7D%20R%5E2%20=%20R%5E2_%7B%5Ctext%7BFull%7D%7D%20-%20R%5E2_%7B%5Ctext%7BNull%7D%7D"></p>
<p>This isolates the variance explained specifically by genetics, over and above known covariates.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.linear_model <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> LinearRegression</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> r2_score</span>
<span id="cb1-3"></span>
<span id="cb1-4">null_model.fit(X_cov, y)</span>
<span id="cb1-5">r2_null <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_score(y, null_model.predict(X_cov))</span>
<span id="cb1-6"></span>
<span id="cb1-7">full_model.fit(X_full, y)</span>
<span id="cb1-8">r2_full <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_score(y, full_model.predict(X_full))</span>
<span id="cb1-9"></span>
<span id="cb1-10">incremental_r2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_full <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> r2_null</span></code></pre></div></div>
</section>
<section id="disease-traits-auc-pseudo-r²-liability-scale-r²" class="level2" data-number="1.2">
<h2 data-number="1.2" class="anchored" data-anchor-id="disease-traits-auc-pseudo-r²-liability-scale-r²"><span class="header-section-number">1.2</span> Disease Traits: AUC, Pseudo-R², Liability-Scale R²</h2>
<p>Binary case/control outcomes need logistic regression and different metrics:</p>
<ul>
<li><strong>Pseudo-R²</strong> (McFadden, Nagelkerke, Cox-Snell) — analogous to R² but derived from a logistic model; interpretation differs from linear R², but larger is still better.</li>
<li><strong>AUC</strong> (Area Under the ROC Curve) — the probability that a randomly chosen case receives a higher predicted risk than a randomly chosen control.</li>
</ul>
<table class="caption-top table">
<thead>
<tr class="header">
<th>AUC</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0.50</td>
<td>Random guessing</td>
</tr>
<tr class="even">
<td>0.60</td>
<td>Weak</td>
</tr>
<tr class="odd">
<td>0.70</td>
<td>Moderate</td>
</tr>
<tr class="even">
<td>0.80</td>
<td>Strong</td>
</tr>
<tr class="odd">
<td>0.90</td>
<td>Excellent</td>
</tr>
</tbody>
</table>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> roc_auc_score</span>
<span id="cb2-2">auc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> roc_auc_score(y_true, prs_scores)</span></code></pre></div></div>
<p>Real-world AUCs vary widely by trait and method: basic clumping-and-thresholding PRS for coronary artery disease or type 2 diabetes often land around 0.57–0.60, while well-optimized, large-biobank PRS have reported AUCs as high as 0.79–0.81 for coronary artery disease. There’s no single “typical” number — it depends heavily on trait architecture, discovery sample size, and how the PRS was built.</p>
<ul>
<li><strong>Liability-scale R²</strong> — case/control samples are usually enriched for cases relative to the true population prevalence, so raw R² on the observed scale can be misleading. The liability threshold model treats disease as arising once an underlying continuous liability (genetics + environment + noise) crosses a threshold; liability-scale R² estimates the proportion of that underlying liability explained by the PRS. This metric is especially common in psychiatric genetics.</li>
</ul>
</section>
<section id="risk-stratification-and-odds-ratios" class="level2" data-number="1.3">
<h2 data-number="1.3" class="anchored" data-anchor-id="risk-stratification-and-odds-ratios"><span class="header-section-number">1.3</span> Risk Stratification and Odds Ratios</h2>
<p>Individuals are commonly split into PRS groups — deciles are typical — and disease prevalence compared across groups. Example: bottom decile odds ratio = 1.0 (reference), top decile odds ratio = 3.5, meaning individuals in the top PRS decile have 3.5× the disease odds of those in the bottom decile. A useful PRS shows monotonically increasing risk from lowest to highest group.</p>
</section>
<section id="avoiding-overfitting-discovery-tuning-and-target-sets" class="level2" data-number="1.4">
<h2 data-number="1.4" class="anchored" data-anchor-id="avoiding-overfitting-discovery-tuning-and-target-sets"><span class="header-section-number">1.4</span> Avoiding Overfitting: Discovery, Tuning, and Target Sets</h2>
<p>A major pitfall: building a PRS, testing many parameter choices, picking the best-performing one, and evaluating on the <em>same</em> individuals used for tuning — this inflates the apparent accuracy, because the model has effectively already “seen” the answer. The standard fix is three independent datasets:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Dataset</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Discovery</strong></td>
<td>Runs the GWAS, produces SNP effect estimates</td>
</tr>
<tr class="even">
<td><strong>Tuning</strong></td>
<td>Optimizes parameters (p-value thresholds, clumping settings, hyperparameters)</td>
</tr>
<tr class="odd">
<td><strong>Target</strong></td>
<td>Used once, to report final unbiased prediction performance</td>
</tr>
</tbody>
</table>
<p>If individuals overlap between discovery and target sets, prediction accuracy is artificially inflated. These three samples must remain independent — this is the gold standard for reporting PRS performance.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Quantitative traits are evaluated with incremental R²; disease traits with AUC, pseudo-R², liability-scale R², and odds ratios. Risk stratification (typically by decile) gives an intuitive picture of prediction performance. Overfitting from re-using tuning data is one of the most common and serious mistakes in PRS evaluation — discovery, tuning, and target datasets must stay independent.</p>
</blockquote>
</section>
</section>
<section id="clumping-and-p-value-thresholding-cpt" class="level1" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Clumping and P-Value Thresholding (C+PT)</h1>
<p>Given GWAS summary statistics, how do we decide which SNPs actually go into a PRS? Naively including every SNP creates problems: many SNPs are highly correlated via LD, many have noisy or negligible effect estimates, and millions of SNPs together introduce substantial statistical noise. <strong>Clumping and P-value Thresholding (C+PT)</strong> was one of the earliest and most influential answers to this, and despite newer Bayesian methods, it remains a widely used baseline.</p>
<section id="why-not-just-use-every-snp" class="level2" data-number="2.1">
<h2 data-number="2.1" class="anchored" data-anchor-id="why-not-just-use-every-snp"><span class="header-section-number">2.1</span> Why Not Just Use Every SNP?</h2>
<p>A GWAS hit on chromosome 6 might show 5 SNPs all with p-values around <img src="https://latex.codecogs.com/png.latex?10%5E%7B-10%7D">–<img src="https://latex.codecogs.com/png.latex?10%5E%7B-12%7D"> — not 5 independent discoveries, but the same underlying signal viewed through SNPs inherited together via LD. Including all of them in a PRS effectively double- (or quintuple-) counts the same genetic information, producing redundant information, inflated variance, overfitting, and reduced prediction accuracy.</p>
</section>
<section id="the-two-step-procedure" class="level2" data-number="2.2">
<h2 data-number="2.2" class="anchored" data-anchor-id="the-two-step-procedure"><span class="header-section-number">2.2</span> The Two-Step Procedure</h2>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BGWAS%20Summary%20Statistics%7D%20%5Crightarrow%20%5Ctext%7BClumping%7D%20%5Crightarrow%20%5Ctext%7BP-value%20Thresholding%7D%20%5Crightarrow%20%5Ctext%7BFinal%20SNP%20Set%7D%20%5Crightarrow%20%5Ctext%7BPolygenic%20Score%7D"></p>
<p><strong>Step 1 — Clumping</strong> removes redundant SNPs, keeping the most significant SNP in each LD region and discarding its correlated neighbors:</p>
<ol type="1">
<li>Sort SNPs by p-value (most significant first).</li>
<li>Select the most significant remaining SNP.</li>
<li>Remove all SNPs within a specified window (e.g.&nbsp;250 kb) whose LD with it exceeds a threshold (e.g.&nbsp;<img src="https://latex.codecogs.com/png.latex?r%5E2%20%3E%200.1">).</li>
<li>Move to the next remaining SNP and repeat until all SNPs are processed.</li>
</ol>
<table class="caption-top table">
<thead>
<tr class="header">
<th><img src="https://latex.codecogs.com/png.latex?r%5E2"> threshold</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0.1</td>
<td>Strict — removes more SNPs</td>
</tr>
<tr class="even">
<td>0.2</td>
<td>Moderate</td>
</tr>
<tr class="odd">
<td>0.5</td>
<td>Relaxed</td>
</tr>
</tbody>
</table>
<p><strong>Step 2 — P-value thresholding.</strong> After clumping, still-many SNPs must be filtered by significance. Researchers typically test several thresholds — <img src="https://latex.codecogs.com/png.latex?5%5Ctimes10%5E%7B-8%7D">, <img src="https://latex.codecogs.com/png.latex?10%5E%7B-6%7D">, <img src="https://latex.codecogs.com/png.latex?10%5E%7B-4%7D">, <img src="https://latex.codecogs.com/png.latex?10%5E%7B-2%7D">, 0.05, 0.1, 0.5, 1.0 — and pick whichever gives the best held-out prediction. Restricting to genome-wide-significant SNPs alone (<img src="https://latex.codecogs.com/png.latex?P%20%3C%205%5Ctimes10%5E%7B-8%7D">) is tempting but usually suboptimal for highly polygenic traits: many true causal variants never individually reach that threshold, so overly strict cutoffs discard real signal.</p>
<p><strong>The tuning process.</strong> Compare incremental <img src="https://latex.codecogs.com/png.latex?R%5E2"> across thresholds on a tuning set:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Threshold</th>
<th>Incremental R²</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>5e-8</td>
<td>0.03</td>
</tr>
<tr class="even">
<td>1e-6</td>
<td>0.05</td>
</tr>
<tr class="odd">
<td>1e-4</td>
<td>0.08</td>
</tr>
<tr class="even">
<td><strong>0.01</strong></td>
<td><strong>0.11</strong></td>
</tr>
<tr class="odd">
<td>0.05</td>
<td>0.09</td>
</tr>
</tbody>
</table>
<p>Here 0.01 wins. This produces the classic <strong>hump-shaped curve</strong>: too few SNPs misses real signal (low accuracy), a moderate number captures the optimal balance (peak accuracy), and too many SNPs lets noise dominate (accuracy falls again).</p>
</section>
<section id="scoring-and-practical-use" class="level2" data-number="2.3">
<h2 data-number="2.3" class="anchored" data-anchor-id="scoring-and-practical-use"><span class="header-section-number">2.3</span> Scoring and Practical Use</h2>
<p>The final score uses the same formula as before, restricted to the selected SNP set:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPRS%7D_i%20=%20%5Csum_%7Bj=1%7D%5E%7Bm%7D%20%5Chat%5Cbeta_j%5C,%20x_%7Bij%7D"></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb3-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> target_data <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb3-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--score</span> selected_snps.txt 1 2 3 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb3-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> prs_scores</span></code></pre></div></div>
<p>(Column 1 = SNP ID, column 2 = effect allele, column 3 = effect size — PLINK multiplies genotype counts by effects and sums.)</p>
</section>
<section id="strengths-and-limitations" class="level2" data-number="2.4">
<h2 data-number="2.4" class="anchored" data-anchor-id="strengths-and-limitations"><span class="header-section-number">2.4</span> Strengths and Limitations</h2>
<p><strong>Strengths:</strong> simple, computationally cheap, works directly from summary statistics, easy to reproduce — hence its continued use as the standard baseline. <strong>Limitations:</strong> discards potentially useful SNPs during clumping, handles LD only indirectly (via pruning, not explicit modeling), treats each SNP’s effect independently rather than jointly, and requires threshold tuning (adding complexity and overfitting risk).</p>
<p>These limitations motivated whole-genome regression and Bayesian methods — BLUP, SBLUP, LDpred, BayesR, BayesC, SBayesR, SBayesRC — which use all SNPs, model LD directly, and apply shrinkage. C+PT nonetheless remains the essential conceptual starting point for understanding them.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> C+PT selects SNPs in two steps: clumping removes LD-redundant SNPs, and p-value thresholding filters by significance, typically tuned across several candidate cutoffs. Prediction accuracy follows a hump-shaped curve against threshold stringency. C+PT is simple and widely used, but discards information and ignores joint LD structure — limitations that motivated modern Bayesian PRS methods.</p>
</blockquote>
</section>
</section>
<section id="best-linear-unbiased-prediction-blup" class="level1" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> Best Linear Unbiased Prediction (BLUP)</h1>
<p>C+PT discards many SNPs, ignores joint LD structure, treats SNPs independently, and requires threshold tuning. <strong>BLUP</strong> represents a conceptual shift: use <em>every</em> SNP simultaneously rather than selecting a subset. Understanding BLUP matters because modern Bayesian methods (BayesR, SBayesR) are direct extensions of it.</p>
<section id="the-infinitesimal-model" class="level2" data-number="3.1">
<h2 data-number="3.1" class="anchored" data-anchor-id="the-infinitesimal-model"><span class="header-section-number">3.1</span> The Infinitesimal Model</h2>
<p>BLUP rests on one of the oldest ideas in quantitative genetics — the <strong>infinitesimal model</strong>: every SNP contributes to the trait, each with a very small effect, drawn from a shared normal distribution <img src="https://latex.codecogs.com/png.latex?%5Cbeta_j%20%5Csim%20N(0,%20%5Csigma_%5Cbeta%5E2)">. Most SNP effects cluster near zero, symmetric around it, with very large effects rare. This is a surprisingly good approximation for many highly polygenic traits (height, BMI, schizophrenia — GWAS repeatedly show thousands of associated variants each).</p>
<p><strong>“Best Linear Unbiased Prediction”</strong> breaks down as: <strong>Best</strong> = smallest prediction error variance among linear unbiased estimators; <strong>Linear</strong> = prediction is a linear combination of SNP effects (<img src="https://latex.codecogs.com/png.latex?%5Chat%20y%20=%20X%5Chat%5Cbeta">); <strong>Unbiased</strong> = predictions aren’t systematically too high or too low.</p>
</section>
<section id="the-mixed-model-framework" class="level2" data-number="3.2">
<h2 data-number="3.2" class="anchored" data-anchor-id="the-mixed-model-framework"><span class="header-section-number">3.2</span> The Mixed Model Framework</h2>
<p><img src="https://latex.codecogs.com/png.latex?y%20=%20Xb%20+%20Zu%20+%20e"></p>
<p><img src="https://latex.codecogs.com/png.latex?Xb"> are <strong>fixed effects</strong> (known covariates like age, sex, principal components, batch); <img src="https://latex.codecogs.com/png.latex?Zu"> is the <strong>genetic component</strong>, treated as a <strong>random effect</strong>: <img src="https://latex.codecogs.com/png.latex?u%20%5Csim%20N(0,%20G%5Csigma_g%5E2)">, where <img src="https://latex.codecogs.com/png.latex?G"> is the <strong>Genetic Relationship Matrix (GRM)</strong> — pairwise genetic similarity between individuals — and <img src="https://latex.codecogs.com/png.latex?%5Csigma_g%5E2"> is genetic variance. Rather than estimating each SNP’s effect independently, BLUP models their <em>collective</em> contribution via this relationship structure: more genetically similar individuals are expected to be more phenotypically similar.</p>
</section>
<section id="shrinkage" class="level2" data-number="3.3">
<h2 data-number="3.3" class="anchored" data-anchor-id="shrinkage"><span class="header-section-number">3.3</span> Shrinkage</h2>
<p>BLUP doesn’t trust raw GWAS estimates fully — it pulls them toward zero, more aggressively for small/noisy estimates than large ones. Example: GWAS effects of 0.40, 0.05, 0.01 might become BLUP effects of 0.25, 0.03, 0.005. Because small-sample GWAS estimates can be inflated by chance, shrinkage separates “mostly signal” from “signal + noise,” reducing overfitting and improving out-of-sample prediction.</p>
<p>PRS calculation is otherwise unchanged — <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPRS%7D_i%20=%20%5Csum_j%20%5Chat%5Cbeta_j%20x_%7Bij%7D"> — the difference from C+PT is simply that <em>every</em> SNP contributes, not a selected subset.</p>
</section>
<section id="advantages-and-limitations" class="level2" data-number="3.4">
<h2 data-number="3.4" class="anchored" data-anchor-id="advantages-and-limitations"><span class="header-section-number">3.4</span> Advantages and Limitations</h2>
<p><strong>Advantages:</strong> uses all SNPs (no discarding), no arbitrary p-value thresholds to tune, handles polygenicity naturally, and shrinkage reduces overfitting.</p>
<p><strong>Limitations:</strong> assumes every SNP has a non-zero effect (unrealistic — many SNPs likely have none), assumes a <em>single</em> normal distribution for all effects (real traits likely have null, small-, medium-, and large-effect SNP classes that a single distribution can’t represent), and struggles to incorporate sparse architectures or functional annotations.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Feature</th>
<th>C+PT</th>
<th>BLUP</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Uses all SNPs</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>Requires tuning</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr class="odd">
<td>Models LD directly</td>
<td>Partially</td>
<td>Better</td>
</tr>
<tr class="even">
<td>Shrinkage</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="odd">
<td>Computational complexity</td>
<td>Low</td>
<td>Moderate</td>
</tr>
</tbody>
</table>
<p>BLUP’s single-distribution assumption motivated researchers to ask: what if many SNPs truly have zero effect, effect sizes come from multiple distributions, or biological annotations could be incorporated? Answering these questions led to Bayesian methods (BayesA, BayesB, BayesC, BayesR, SBayesR, SBayesRC) — direct generalizations of the BLUP framework that relax its restrictive assumptions.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> BLUP is a whole-genome regression method using all SNPs simultaneously, under the infinitesimal-model assumption that effects are normally distributed. It relies on a Genetic Relationship Matrix and applies shrinkage to reduce overfitting, eliminating the need for clumping or p-value thresholds. Its core limitation — one shared normal distribution for every SNP effect — motivated the Bayesian methods that followed.</p>
</blockquote>
</section>
</section>
<section id="bayesian-methods-and-mcmc" class="level1" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> Bayesian Methods and MCMC</h1>
<p>BLUP’s key limitation is assuming every SNP’s effect is drawn from one shared normal distribution — unrealistic, since many SNPs likely have zero effect while a few have outsized ones. <strong>Bayesian methods</strong> relax this by treating SNP effects as random variables with more flexible priors — the foundation for BayesA, BayesB, BayesC, BayesR, and their modern summary-statistics descendants SBayesR and SBayesRC.</p>
<section id="the-bayesian-philosophy" class="level2" data-number="4.1">
<h2 data-number="4.1" class="anchored" data-anchor-id="the-bayesian-philosophy"><span class="header-section-number">4.1</span> The Bayesian Philosophy</h2>
<p>Classical (frequentist) statistics treats a parameter like <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> as a fixed but unknown true value. Bayesian statistics instead asks for its full probability distribution, combining:</p>
<ul>
<li><strong>Prior beliefs</strong> — what we assume before seeing data, e.g.&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Cbeta_j%20%5Csim%20N(0,%20%5Csigma%5E2)">, encoding “most effects are small, positive and negative are equally likely, large effects are rare.”</li>
<li><strong>The likelihood</strong> — how probable the observed data is under a given parameter value.</li>
</ul>
<p>via <strong>Bayes’ theorem</strong>: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BPosterior%7D%20%5Cpropto%20%5Ctext%7BPrior%7D%20%5Ctimes%20%5Ctext%7BLikelihood%7D">. If the prior expects <img src="https://latex.codecogs.com/png.latex?%5Cbeta%20%5Capprox%200"> but the GWAS data strongly suggests <img src="https://latex.codecogs.com/png.latex?%5Cbeta%20%5Capprox%200.3">, the posterior lands somewhere in between (e.g.&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Cbeta%20%5Capprox%200.2">) — naturally shrinking noisy GWAS estimates toward more plausible values, which often improves prediction.</p>
</section>
<section id="bayesc-and-the-spike-and-slab-prior" class="level2" data-number="4.2">
<h2 data-number="4.2" class="anchored" data-anchor-id="bayesc-and-the-spike-and-slab-prior"><span class="header-section-number">4.2</span> BayesC and the Spike-and-Slab Prior</h2>
<p><strong>BayesC</strong> was the first influential model of this kind: some SNPs have exactly zero effect (<img src="https://latex.codecogs.com/png.latex?%5Cbeta_j%20=%200">, probability <img src="https://latex.codecogs.com/png.latex?%5Cpi">), others are drawn from a normal distribution (<img src="https://latex.codecogs.com/png.latex?%5Cbeta_j%20%5Csim%20N(0,%5Csigma_%5Cbeta%5E2)">, probability <img src="https://latex.codecogs.com/png.latex?1-%5Cpi">). This is a <strong>spike-and-slab prior</strong> — a “spike” at zero for null SNPs, a “slab” (broader distribution) for real effects. Rather than forcing every SNP to contribute, BayesC lets the data determine which SNPs matter, reducing noise and improving shrinkage — especially when the true genetic architecture is sparse (e.g.&nbsp;100 causal variants among 1,000,000 measured SNPs, which BLUP handles poorly).</p>
</section>
<section id="why-mcmc-is-needed" class="level2" data-number="4.3">
<h2 data-number="4.3" class="anchored" data-anchor-id="why-mcmc-is-needed"><span class="header-section-number">4.3</span> Why MCMC Is Needed</h2>
<p>Bayesian posteriors for a million SNPs at once have no closed-form solution — the parameter space is far too high-dimensional to compute directly. <strong>Markov Chain Monte Carlo (MCMC)</strong> solves this by <em>sampling</em> from the posterior instead of solving it analytically. It combines two ideas: a <strong>Markov chain</strong> (each new state depends only on the current state, not the full history) and <strong>Monte Carlo</strong> sampling (random draws used to approximate otherwise intractable quantities, in the spirit of estimating <img src="https://latex.codecogs.com/png.latex?%5Cpi"> by randomly throwing darts at a circle inscribed in a square). Over many iterations, MCMC spends more time in high-posterior-probability regions and less in low-probability ones, and the accumulated samples reconstruct the posterior distribution.</p>
<p><strong>Gibbs sampling</strong> is the standard MCMC algorithm here: rather than updating SNP effects (<img src="https://latex.codecogs.com/png.latex?%5Cbeta">), genetic variance (<img src="https://latex.codecogs.com/png.latex?%5Csigma_%5Cbeta%5E2">), residual variance (<img src="https://latex.codecogs.com/png.latex?%5Csigma_e%5E2">), and the inclusion probability (<img src="https://latex.codecogs.com/png.latex?%5Cpi">) all simultaneously, it updates them one at a time, cycling through thousands of iterations:</p>
<pre class="text"><code>Update β → Update σ²β → Update σ²e → Update π → repeat</code></pre>
<p><strong>Burn-in.</strong> Early samples reflect arbitrary starting values rather than the true posterior, so they’re discarded — e.g.&nbsp;of 50,000 total iterations, the first 10,000 might be burn-in, leaving 40,000 retained samples for inference.</p>
<p><strong>Convergence diagnostics.</strong> A <strong>trace plot</strong> (parameter value vs.&nbsp;iteration) that fluctuates stably around a constant mean suggests convergence; a plot with a clear upward/downward trend suggests the chain hasn’t stabilized yet.</p>
<p><strong>Extracting estimates.</strong> After convergence, the posterior mean <img src="https://latex.codecogs.com/png.latex?%5Cbar%5Cbeta%20=%20%5Cfrac%7B1%7D%7BN%7D%5Csum_i%20%5Cbeta%5E%7B(i)%7D"> becomes the final SNP effect estimate, and posterior variance quantifies uncertainty (large variance = low confidence). A SNP’s <strong>Posterior Inclusion Probability (PIP)</strong> is simply the fraction of retained iterations in which it was included — e.g.&nbsp;included in 45,000 of 50,000 samples gives PIP = 0.90.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>PIP</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0.01</td>
<td>Almost certainly irrelevant</td>
</tr>
<tr class="even">
<td>0.10</td>
<td>Weak evidence</td>
</tr>
<tr class="odd">
<td>0.50</td>
<td>Moderate evidence</td>
</tr>
<tr class="even">
<td>0.90</td>
<td>Strong evidence</td>
</tr>
<tr class="odd">
<td>0.99</td>
<td>Very strong evidence</td>
</tr>
</tbody>
</table>
</section>
<section id="strengths-weaknesses-and-the-path-forward" class="level2" data-number="4.4">
<h2 data-number="4.4" class="anchored" data-anchor-id="strengths-weaknesses-and-the-path-forward"><span class="header-section-number">4.4</span> Strengths, Weaknesses, and the Path Forward</h2>
<p>MCMC provides full posterior distributions, honest uncertainty estimates, and PIPs — real advantages over point-estimate methods. But it’s also computationally expensive (1 million SNPs × 50,000 iterations can take hours to days and substantial memory), can converge slowly, and can be hard to diagnose. This computational burden directly motivated <strong>SBayesR</strong> and <strong>SBayesRC</strong>, which achieve similar Bayesian flexibility using summary statistics and efficient sparse-matrix methods instead of raw individual-level MCMC over the full genotype matrix.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> Bayesian methods treat SNP effects as random variables with flexible priors rather than a single shared distribution. BayesC’s spike-and-slab prior lets some SNPs have exactly zero effect. Because the resulting posteriors have no closed-form solution, MCMC (typically Gibbs sampling) approximates them via iterative random sampling, discarding early “burn-in” draws and using posterior means and inclusion probabilities as final estimates. MCMC’s computational cost motivated the summary-statistics-based methods that followed.</p>
</blockquote>
</section>
</section>
<section id="sbayesr-bayesian-prediction-from-summary-statistics" class="level1" data-number="5">
<h1 data-number="5"><span class="header-section-number">5</span> SBayesR: Bayesian Prediction from Summary Statistics</h1>
<p>MCMC over individual-level genotypes is powerful but computationally expensive at biobank scale. <strong>SBayesR</strong> (summary-data-based BayesR) reformulates the BayesR model to run on GWAS <strong>summary statistics</strong> plus an <strong>LD reference panel</strong>, instead of raw genotypes — making Bayesian polygenic prediction tractable at scale. It’s now one of the most widely used methods for building PRS from GWAS summary data, and the foundation for SBayesRC.</p>
<section id="why-sbayesr-was-developed" class="level2" data-number="5.1">
<h2 data-number="5.1" class="anchored" data-anchor-id="why-sbayesr-was-developed"><span class="header-section-number">5.1</span> Why SBayesR Was Developed</h2>
<p>Each earlier method had a specific gap: C+PT discards SNPs and ignores joint LD; BLUP forces every SNP into a single effect-size distribution; individual-level BayesC models sparsity well but needs raw genotype data and is computationally expensive at scale. Researchers wanted Bayesian flexibility, summary-statistics compatibility, and scalability together — SBayesR was the answer, implemented in the <strong>GCTB</strong> software.</p>
</section>
<section id="the-mixture-prior" class="level2" data-number="5.2">
<h2 data-number="5.2" class="anchored" data-anchor-id="the-mixture-prior"><span class="header-section-number">5.2</span> The Mixture Prior</h2>
<p>BLUP assumes one shared distribution, <img src="https://latex.codecogs.com/png.latex?%5Cbeta_j%20%5Csim%20N(0,%5Csigma_%5Cbeta%5E2)">, for every SNP. BayesR (and SBayesR) instead uses a <strong>mixture of normal distributions</strong> with a point mass at zero:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Cbeta_j%20%5Csim%20%5Csum_%7Bk=1%7D%5E%7BK%7D%20%5Cpi_k%5C,%20N(0,%20%5Cgamma_k%20%5Csigma_%5Cbeta%5E2)"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?%5Cpi_k"> is the proportion of SNPs in class <img src="https://latex.codecogs.com/png.latex?k"> and <img src="https://latex.codecogs.com/png.latex?%5Cgamma_k"> scales that class’s variance. The standard BayesR/SBayesR configuration uses <strong>four components</strong> — <img src="https://latex.codecogs.com/png.latex?%5Cgamma%20=%20(0,%5C%200.01,%5C%200.1,%5C%201)"> — representing zero effect, small effect, medium effect, and large effect classes respectively (component 1 is a literal point mass at zero; components 2–4 scale <img src="https://latex.codecogs.com/png.latex?%5Csigma_%5Cbeta%5E2"> by 0.01×, 0.1×, and 1× respectively). A typical starting mixture might set <img src="https://latex.codecogs.com/png.latex?%5Cpi%20=%20(0.95,%5C%200.02,%5C%200.02,%5C%200.01)"> — most SNPs assigned near-zero effect, a small number carrying most of the real signal — and SBayesR estimates the actual proportions from the data during MCMC, which itself provides insight into the trait’s genetic architecture.</p>
</section>
<section id="recovering-joint-effects-from-marginal-gwas-statistics" class="level2" data-number="5.3">
<h2 data-number="5.3" class="anchored" data-anchor-id="recovering-joint-effects-from-marginal-gwas-statistics"><span class="header-section-number">5.3</span> Recovering Joint Effects from Marginal GWAS Statistics</h2>
<p>GWAS summary statistics report <strong>marginal</strong> effects — each SNP tested one at a time, ignoring correlation with its neighbors. The relationship to the true joint effects is approximately <img src="https://latex.codecogs.com/png.latex?b%20=%20R%5Cbeta%20+%20%5Cepsilon">, where <img src="https://latex.codecogs.com/png.latex?b"> is the vector of observed GWAS effects, <img src="https://latex.codecogs.com/png.latex?R"> is the LD matrix, and <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> is the joint effect vector SBayesR aims to recover. If rs1, rs2, rs3 are strongly correlated, a naive analysis might spread signal across all three; modeling them jointly through <img src="https://latex.codecogs.com/png.latex?R"> lets SBayesR assign most of the signal to one and shrink the others toward zero — improving both interpretability and prediction.</p>
</section>
<section id="making-this-computationally-tractable" class="level2" data-number="5.4">
<h2 data-number="5.4" class="anchored" data-anchor-id="making-this-computationally-tractable"><span class="header-section-number">5.4</span> Making This Computationally Tractable</h2>
<p>A full LD matrix for 1 million SNPs has <img src="https://latex.codecogs.com/png.latex?10%5E%7B12%7D"> entries — far too large to handle directly. Because most SNPs are only correlated with nearby variants, the vast majority of LD matrix entries are effectively zero, so SBayesR stores a <strong>sparse</strong> representation (reduced memory, faster computation), and can further use an eigen-decomposition <img src="https://latex.codecogs.com/png.latex?R%20=%20U%5CLambda%20U%5ET"> to reduce the computational burden during MCMC sampling. These optimizations are what make biobank-scale SBayesR analyses feasible at all.</p>
</section>
<section id="running-sbayesr" class="level2" data-number="5.5">
<h2 data-number="5.5" class="anchored" data-anchor-id="running-sbayesr"><span class="header-section-number">5.5</span> Running SBayesR</h2>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gctb</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--sbayes</span> R <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--ldm</span> ukbEURu_hm3_sparse <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--gwas-summary</span> trait.ma <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> trait_sbayesr</span></code></pre></div></div>
<p>Internally, GCTB reads the summary statistics, loads the LD matrix, runs MCMC (updating SNP effects, mixture-component membership, genetic variance, and residual variance each iteration), and outputs posterior mean SNP effects to <code>trait_sbayesr.snpRes</code> and MCMC/parameter diagnostics to <code>trait_sbayesr.parRes</code>. These posterior effects are typically less noisy than raw GWAS effects, and are combined with target genotypes using PLINK’s <code>--score</code>, exactly as in earlier methods.</p>
</section>
<section id="strengths-and-limitations-1" class="level2" data-number="5.6">
<h2 data-number="5.6" class="anchored" data-anchor-id="strengths-and-limitations-1"><span class="header-section-number">5.6</span> Strengths and Limitations</h2>
<p><strong>Strengths:</strong> uses all SNPs, models LD directly (joint rather than marginal effects), a flexible mixture prior that better matches real genetic architecture, works from summary statistics alone, and scales to biobank-sized analyses.</p>
<p><strong>Limitations:</strong> treats every SNP as equally likely to be causal <em>a priori</em> — no biological information about coding regions, regulatory elements, or conservation is used; results depend on how well the LD reference panel matches the GWAS population; and it remains more computationally demanding than C+PT.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Feature</th>
<th>C+PT</th>
<th>BLUP</th>
<th>SBayesR</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Uses all SNPs</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>Models LD</td>
<td>Partial</td>
<td>Better</td>
<td>Yes (jointly)</td>
</tr>
<tr class="odd">
<td>Summary statistics only</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>Mixture prior</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="odd">
<td>Sparse architecture</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p>That first limitation — ignoring biology — is exactly what SBayesRC addresses next.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> SBayesR extends BayesR to work from GWAS summary statistics and an LD reference panel, using a four-component mixture prior (a zero-effect spike plus three non-zero variance classes) instead of BLUP’s single normal distribution. Sparse LD matrices and eigen-decomposition make this tractable at biobank scale. It doesn’t yet use any biological/functional information — the motivation for SBayesRC.</p>
</blockquote>
</section>
</section>
<section id="sbayesrc-adding-functional-annotations" class="level1" data-number="6">
<h1 data-number="6"><span class="header-section-number">6</span> SBayesRC: Adding Functional Annotations</h1>
<p>SBayesR treats every SNP as equally likely to be causal before seeing the data — but decades of molecular biology say that’s not realistic. A SNP sitting in a protein-coding exon and a SNP sitting in an intergenic region shouldn’t necessarily get the same prior probability of being causal, even with identical GWAS p-values. <strong>SBayesRC</strong> extends SBayesR by letting <strong>functional annotations</strong> inform those priors.</p>
<section id="functional-annotations-and-heritability-enrichment" class="level2" data-number="6.1">
<h2 data-number="6.1" class="anchored" data-anchor-id="functional-annotations-and-heritability-enrichment"><span class="header-section-number">6.1</span> Functional Annotations and Heritability Enrichment</h2>
<p>Functional annotations describe biological properties of genomic regions — coding sequence, promoters, enhancers, evolutionarily conserved regions, open chromatin (DNase hypersensitivity sites), histone marks, and more. Each SNP can be tagged with one or more of these categories, forming an annotation matrix (SNP × annotation, 0/1 entries).</p>
<p>The key concept is <strong>heritability enrichment</strong>: some annotation categories explain disproportionately more heritability than their share of the genome would suggest. Illustratively:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Annotation</th>
<th>SNP Fraction</th>
<th>Heritability Fraction</th>
<th>Enrichment</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Coding</td>
<td>2%</td>
<td>10%</td>
<td>5×</td>
</tr>
<tr class="even">
<td>Conserved</td>
<td>5%</td>
<td>20%</td>
<td>4×</td>
</tr>
<tr class="odd">
<td>Intergenic</td>
<td>50%</td>
<td>20%</td>
<td>0.4×</td>
</tr>
</tbody>
</table>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BEnrichment%7D%20=%20%5Cfrac%7B%5Ctext%7BHeritability%20Proportion%7D%7D%7B%5Ctext%7BSNP%20Proportion%7D%7D"></p>
<p>An enrichment of 5 means that annotation category contributes five times more heritability than its size alone would predict — flagging it as more likely to harbor causal variants, and letting SBayesRC assign it a higher prior probability of non-zero effect during inference.</p>
</section>
<section id="the-model-change" class="level2" data-number="6.2">
<h2 data-number="6.2" class="anchored" data-anchor-id="the-model-change"><span class="header-section-number">6.2</span> The Model Change</h2>
<p>In SBayesR, the mixture-component probabilities <img src="https://latex.codecogs.com/png.latex?%5Cpi_k"> are the same for every SNP. In SBayesRC, <img src="https://latex.codecogs.com/png.latex?%5Cpi_k"> becomes a function of each SNP’s annotations — so two SNPs with identical GWAS evidence can receive different prior probabilities of being causal, depending on their biological context. This lets SBayesRC combine statistical evidence <em>and</em> biological plausibility, rather than statistical evidence alone.</p>
</section>
<section id="running-sbayesrc" class="level2" data-number="6.3">
<h2 data-number="6.3" class="anchored" data-anchor-id="running-sbayesrc"><span class="header-section-number">6.3</span> Running SBayesRC</h2>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gctb</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb6-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--sbayes</span> RC <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb6-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--ldm</span> ukbEURu_hm3_sparse <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb6-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--annot</span> annotations.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb6-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--gwas-summary</span> trait.ma <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb6-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> trait_sbayesrc</span></code></pre></div></div>
<p>The only new input compared with SBayesR is the annotation file. Large-scale implementations commonly draw on baselineLD-style annotation sets spanning coding regions, conservation, regulatory elements, histone modifications, and gene expression — often dozens to hundreds of categories. Typical outputs add <code>trait_sbayesrc.enrich</code>, summarizing annotation-specific heritability enrichment, alongside the usual <code>.snpRes</code> and <code>.parRes</code> files.</p>
</section>
<section id="advantages-and-limitations-1" class="level2" data-number="6.4">
<h2 data-number="6.4" class="anchored" data-anchor-id="advantages-and-limitations-1"><span class="header-section-number">6.4</span> Advantages and Limitations</h2>
<p>Because it draws on both statistical <em>and</em> biological evidence, SBayesRC often modestly but consistently outperforms SBayesR across traits. That said, it inherits new failure modes: annotation quality directly affects performance (poor annotations can hurt more than help); it estimates more parameters, adding computational cost; annotations may not transfer cleanly across ancestries; and even the best current annotation sets capture only a fraction of real regulatory biology.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Feature</th>
<th>SBayesR</th>
<th>SBayesRC</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Summary statistics</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>LD modeling</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr class="odd">
<td>Mixture priors</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr class="even">
<td>Functional annotations</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr class="odd">
<td>Heritability enrichment</td>
<td>No</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> SBayesRC extends SBayesR by letting functional annotations modify each SNP’s prior probability of being causal, using heritability enrichment to identify biologically important genomic regions. Combining statistical and biological evidence often modestly improves prediction accuracy over SBayesR alone — though results still depend on annotation quality and completeness, and may not generalize equally across ancestries.</p>
</blockquote>
</section>
</section>
<section id="practical-prs-analysis-prsice-gctb-plink" class="level1" data-number="7">
<h1 data-number="7"><span class="header-section-number">7</span> Practical PRS Analysis: PRSice, GCTB, PLINK</h1>
<p>A complete PRS pipeline, connecting the theory above to actual tools:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BDiscovery%20GWAS%7D%20%5Crightarrow%20%5Ctext%7BSummary%20Stats%20QC%7D%20%5Crightarrow%20%5Ctext%7BPRS%20Method%20(C+PT%20/%20SBayesR%20/%20SBayesRC)%7D%20%5Crightarrow%20%5Ctext%7BPosterior%20SNP%20Effects%7D%20%5Crightarrow%20%5Ctext%7BPLINK%20Scoring%7D%20%5Crightarrow%20%5Ctext%7BPrediction%20Evaluation%7D"></p>
<section id="required-datasets-and-files" class="level2" data-number="7.1">
<h2 data-number="7.1" class="anchored" data-anchor-id="required-datasets-and-files"><span class="header-section-number">7.1</span> Required Datasets and Files</h2>
<p>Three datasets, as in Part 2: <strong>discovery</strong> (produces GWAS summary statistics), <strong>target</strong> (genotypes, phenotypes, covariates for evaluation), and an <strong>LD reference</strong> for methods that need it (SBayesR, SBayesRC, LDpred) — commonly UK Biobank, 1000 Genomes, or HapMap3.</p>
<p>A typical project layout:</p>
<pre class="text"><code>GWAS/         trait.ma
Target/       target.bed, target.bim, target.fam
Covariates/   covariates.txt
Phenotypes/   phenotype.txt
LD/           ukb_ldm/</code></pre>
</section>
<section id="step-1-qc-summary-statistics-and-target-genotypes" class="level2" data-number="7.2">
<h2 data-number="7.2" class="anchored" data-anchor-id="step-1-qc-summary-statistics-and-target-genotypes"><span class="header-section-number">7.2</span> Step 1 — QC Summary Statistics and Target Genotypes</h2>
<p>Check for missing SNP IDs, duplicate variants, strand ambiguity, allele mismatches, and incorrect sample sizes in the summary statistics — poor-quality summary stats reliably wreck downstream prediction.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb8-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> target <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb8-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--geno</span> 0.02 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb8-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--mind</span> 0.02 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb8-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--maf</span> 0.01 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb8-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb8-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> target_QC</span></code></pre></div></div>
</section>
<section id="step-2-cpt-via-prsice" class="level2" data-number="7.3">
<h2 data-number="7.3" class="anchored" data-anchor-id="step-2-cpt-via-prsice"><span class="header-section-number">7.3</span> Step 2 — C+PT via PRSice</h2>
<p><a href="https://choishingwan.github.io/PRSice/">PRSice</a> implements clumping, thresholding, PRS construction, and evaluation in one tool:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Rscript</span> PRSice.R <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--prsice</span> PRSice_linux <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--base</span> trait.ma <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--target</span> target_QC <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pheno</span> phenotype.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cov</span> covariates.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--stat</span> BETA <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--beta</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> PRS_output</span></code></pre></div></div>
<p><code>--base</code> is the GWAS summary file, <code>--target</code> the target genotypes, <code>--pheno</code>/<code>--cov</code> the phenotype and covariates for evaluation. Outputs include <code>PRS_output.best</code> (best p-value threshold), <code>PRS_output.summary</code> (incremental R², SNP counts), and <code>PRS_output.all_score</code> (scores at every threshold tested).</p>
</section>
<section id="step-3-sbayesr-and-sbayesrc-via-gctb" class="level2" data-number="7.4">
<h2 data-number="7.4" class="anchored" data-anchor-id="step-3-sbayesr-and-sbayesrc-via-gctb"><span class="header-section-number">7.4</span> Step 3 — SBayesR and SBayesRC via GCTB</h2>
<p>GCTB needs an LD reference matrix in addition to summary statistics — pre-computed sparse LD matrices derived from UK Biobank reference panels (e.g.&nbsp;<code>ukbEURu_hm3_sparse</code>) are commonly used:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gctb</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--sbayes</span> R <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--ldm</span> ukbEURu_hm3_sparse <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--gwas-summary</span> trait.ma <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb10-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> trait_sbayesr</span></code></pre></div></div>
<p>For SBayesRC, add an annotation file and switch <code>--sbayes R</code> to <code>--sbayes RC</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gctb</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--sbayes</span> RC <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--ldm</span> ukbEURu_hm3_sparse <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--annot</span> annotations.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--gwas-summary</span> trait.ma <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb11-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> trait_sbayesrc</span></code></pre></div></div>
<p>Both produce a <code>.snpRes</code> file with posterior SNP effects, generally less noisy than raw GWAS betas.</p>
</section>
<section id="step-4-scoring-and-evaluation" class="level2" data-number="7.5">
<h2 data-number="7.5" class="anchored" data-anchor-id="step-4-scoring-and-evaluation"><span class="header-section-number">7.5</span> Step 4 — Scoring and Evaluation</h2>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb12-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb12-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> target_QC <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb12-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--score</span> score.txt 1 2 3 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb12-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> target_PRS</span></code></pre></div></div>
<p>producing per-individual scores (<code>FID IID SCORE1_SUM</code>). Evaluate exactly as in Part 2 — compare a full model (<code>Phenotype ~ Sex + Age + PCs + PRS</code>) against a null model (<code>Phenotype ~ Sex + Age + PCs</code>) and take the incremental <img src="https://latex.codecogs.com/png.latex?R%5E2">:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">null_model.fit(X_cov, y)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span>  r2_null <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_score(y, null_model.predict(X_cov))</span>
<span id="cb13-2">full_model.fit(X_full, y)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> r2_full <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_score(y, full_model.predict(X_full))</span>
<span id="cb13-3">incremental_r2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_full <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> r2_null</span></code></pre></div></div>
<p>Then stratify by risk group (e.g.&nbsp;bottom 10% / middle 80% / top 10%) and compare disease prevalence across them.</p>
<p><strong>Illustrative method comparison</strong> (values are trait-dependent, not universal constants):</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Method</th>
<th>Incremental R²</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>C+PT</td>
<td>0.08</td>
</tr>
<tr class="even">
<td>BLUP</td>
<td>0.10</td>
</tr>
<tr class="odd">
<td>SBayesR</td>
<td>0.13</td>
</tr>
<tr class="even">
<td>SBayesRC</td>
<td>0.14</td>
</tr>
</tbody>
</table>
<p>SBayesRC often — not always — achieves the highest accuracy among these; the actual ranking depends on the trait, sample size, and annotation quality available.</p>
</section>
<section id="common-problems-and-best-practices" class="level2" data-number="7.6">
<h2 data-number="7.6" class="anchored" data-anchor-id="common-problems-and-best-practices"><span class="header-section-number">7.6</span> Common Problems and Best Practices</h2>
<p><strong>Common problems:</strong> allele mismatches between summary statistics and target genotypes (the single most frequent source of errors — always harmonize alleles first); an LD reference whose ancestry doesn’t match the GWAS population (degrades accuracy); sample overlap between discovery and target sets (inflates apparent performance); and poor-quality input summary statistics (garbage in, garbage out).</p>
<p><strong>Best practices:</strong> thorough QC at every step, ancestry-matched LD references, strict independence between discovery/tuning/target samples, evaluation only on held-out data, and comparing multiple methods rather than trusting one blindly.</p>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> PRSice runs C+PT end-to-end; GCTB runs SBayesR (<code>--sbayes R</code>) and SBayesRC (<code>--sbayes RC</code>, plus <code>--annot</code>); PLINK’s <code>--score</code> converts posterior SNP effects into individual-level PRS. Allele mismatches and LD reference mismatch are the most common practical failure points — careful QC and ancestry matching matter as much as method choice.</p>
</blockquote>
</section>
</section>
<section id="interpreting-prs-what-do-they-really-mean" class="level1" data-number="8">
<h1 data-number="8"><span class="header-section-number">8</span> Interpreting PRS: What Do They Really Mean?</h1>
<p>A high PRS does not mean “you will get the disease,” and a low PRS does not mean “you’re protected.” Both are common misreadings. A PRS is a statistical predictor, not a diagnosis — understanding its actual meaning matters for responsible use in research, medicine, and public communication.</p>
<section id="relative-position-not-absolute-fate" class="level2" data-number="8.1">
<h2 data-number="8.1" class="anchored" data-anchor-id="relative-position-not-absolute-fate"><span class="header-section-number">8.1</span> Relative Position, Not Absolute Fate</h2>
<p>A PRS represents an individual’s genetic predisposition <strong>relative to others in the same population</strong> — the operative word is <em>relative</em>. A height-PRS analogy: knowing Person C’s PRS is +2.4 and Person A’s is −2.1 doesn’t tell you their exact heights, but does suggest Person C is likely taller than Person A. The same logic carries over to disease risk.</p>
</section>
<section id="relative-risk-vs.-absolute-risk" class="level2" data-number="8.2">
<h2 data-number="8.2" class="anchored" data-anchor-id="relative-risk-vs.-absolute-risk"><span class="header-section-number">8.2</span> Relative Risk vs.&nbsp;Absolute Risk</h2>
<p>These two are frequently conflated. If average disease risk is 10% and the top PRS decile has “3× higher risk” (a <strong>relative risk</strong> statement), the <strong>absolute risk</strong> for that group becomes roughly 30% — meaningfully elevated, but nowhere near certainty. Even high-risk individuals usually don’t develop the disease. This distinction is essential when communicating PRS results to anyone outside a statistics-fluent audience.</p>
</section>
<section id="percentiles-make-raw-scores-interpretable" class="level2" data-number="8.3">
<h2 data-number="8.3" class="anchored" data-anchor-id="percentiles-make-raw-scores-interpretable"><span class="header-section-number">8.3</span> Percentiles Make Raw Scores Interpretable</h2>
<p>A raw score like “PRS = 1.42” means almost nothing by itself — interpretation improves enormously once it’s expressed as a percentile within a reference population (e.g.&nbsp;99th percentile = higher than 99% of people). Most PRS distributions are approximately normal, with most individuals clustering near the middle and extreme scores becoming rarer toward the tails.</p>
<p><strong>Illustrative risk stratification example (coronary artery disease):</strong></p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Group</th>
<th>Disease Rate</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Bottom 10%</td>
<td>3%</td>
</tr>
<tr class="even">
<td>Average</td>
<td>7%</td>
</tr>
<tr class="odd">
<td>Top 10%</td>
<td>18%</td>
</tr>
</tbody>
</table>
<p>Higher PRS tracks with higher disease frequency, but the majority of even the top-decile group still doesn’t develop the disease. Odds ratios (e.g.&nbsp;top decile 3.5× the odds of bottom decile) summarize this pattern compactly, but odds and probability aren’t the same thing and shouldn’t be conflated.</p>
</section>
<section id="prs-is-not-destiny" class="level2" data-number="8.4">
<h2 data-number="8.4" class="anchored" data-anchor-id="prs-is-not-destiny"><span class="header-section-number">8.4</span> PRS Is Not Destiny</h2>
<p>Phenotype = Genetics + Environment + Random effects, roughly speaking — even highly heritable diseases have substantial non-genetic contributors. For type 2 diabetes, diet, physical activity, obesity, smoking, and sleep all matter alongside genetic risk: a high-PRS individual may never develop disease, and a low-PRS individual isn’t guaranteed protection.</p>
<p><strong>Heritability sets a hard ceiling.</strong> If a trait’s heritability is <img src="https://latex.codecogs.com/png.latex?h%5E2%20=%200.40">, only 40% of phenotypic variation is genetic in origin — even a theoretically perfect PRS cannot explain the other 60%, because that variance simply isn’t genetic. A high PRS suggests increased inherited susceptibility and elevated relative risk; it does <strong>not</strong> imply certainty of disease, an immediate clinical diagnosis, or the presence of symptoms.</p>
</section>
<section id="population-portability" class="level2" data-number="8.5">
<h2 data-number="8.5" class="anchored" data-anchor-id="population-portability"><span class="header-section-number">8.5</span> Population Portability</h2>
<p>A PRS trained on a European-ancestry GWAS and applied to an African-ancestry population typically loses substantial predictive accuracy — driven by differing allele frequencies, differing LD patterns (so tag SNPs correlated with a causal variant in one population may be poorly correlated with it in another), and differing environmental exposures. This portability problem is one of the major open challenges in the field (Part 10 covers it further).</p>
</section>
<section id="clinical-and-ethical-considerations" class="level2" data-number="8.6">
<h2 data-number="8.6" class="anchored" data-anchor-id="clinical-and-ethical-considerations"><span class="header-section-number">8.6</span> Clinical and Ethical Considerations</h2>
<p>Potential clinical uses include early screening, targeting preventive interventions, and risk communication as part of personalized medicine — but clinical implementation is still an active area of research, not settled practice. PRS should be one input among many (family history, lifestyle, environmental exposures, medical records, biomarkers), not a standalone basis for major decisions. Open ethical questions include data privacy, potential for discrimination (e.g.&nbsp;insurance, employment), how to communicate risk responsibly, and equitable distribution of benefit across ancestries currently underrepresented in GWAS.</p>
</section>
<section id="common-misinterpretations-corrected" class="level2" data-number="8.7">
<h2 data-number="8.7" class="anchored" data-anchor-id="common-misinterpretations-corrected"><span class="header-section-number">8.7</span> Common Misinterpretations, Corrected</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Misinterpretation</th>
<th>Reality</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>High PRS = disease</td>
<td>False — it’s elevated relative risk, not certainty</td>
</tr>
<tr class="even">
<td>Low PRS = protected</td>
<td>False — non-genetic factors still matter</td>
</tr>
<tr class="odd">
<td>Genetics = destiny</td>
<td>False — environment and chance both contribute substantially</td>
</tr>
<tr class="even">
<td>PRS works equally in every population</td>
<td>False — accuracy varies by ancestry match to the discovery GWAS</td>
</tr>
</tbody>
</table>
<blockquote class="blockquote">
<p><strong>Key takeaways.</strong> A PRS measures relative genetic predisposition, not a diagnosis. Relative risk and absolute risk are different quantities and shouldn’t be conflated; percentiles are usually more interpretable than raw scores. Prediction accuracy is capped by heritability and degrades when applied across ancestries different from the discovery GWAS. Responsible use treats PRS as one input among several, not a standalone predictor of fate.</p>
</blockquote>
</section>
</section>
<section id="the-future-of-prs-multi-ancestry-functional-genomics-precision-medicine" class="level1" data-number="9">
<h1 data-number="9"><span class="header-section-number">9</span> The Future of PRS: Multi-Ancestry, Functional Genomics, Precision Medicine</h1>
<p>Despite real progress — from simple weighted sums to SBayesRC’s Bayesian, LD-aware, annotation-informed models — today’s PRS methods remain far from perfect. Major open challenges: limited cross-ancestry portability, missing heritability, gene-environment interactions, rare variants, and clinical implementation.</p>
<p>Prediction accuracy today varies substantially by trait: it’s generally strongest for traits like height, and more modest for BMI, coronary artery disease, type 2 diabetes, schizophrenia, and especially depression — reflecting real differences in genetic architecture, GWAS sample size, and environmental contribution across traits, not just tool limitations.</p>
<section id="the-multi-ancestry-problem" class="level2" data-number="9.1">
<h2 data-number="9.1" class="anchored" data-anchor-id="the-multi-ancestry-problem"><span class="header-section-number">9.1</span> The Multi-Ancestry Problem</h2>
<p>Most large GWAS to date have been conducted in European-ancestry cohorts, so PRS trained on them predict well <em>within</em> European-ancestry populations but substantially worse when applied to other ancestries. Three main drivers: <strong>differing allele frequencies</strong> (a SNP common in one population may be rare in another, changing its statistical power to contribute to prediction); <strong>differing LD patterns</strong> (a tag SNP correlated with a causal variant in one population may be weakly correlated with it in another, breaking the LD-based logic PRS relies on); and <strong>differing environmental exposures</strong> (diet, healthcare access, socioeconomic conditions), meaning even identical genetics can translate to different outcomes.</p>
<p><strong>Multi-ancestry PRS</strong> methods, combining GWAS data across ancestral groups and modeling both shared and population-specific genetic effects, are an active area of development aimed at improving generalization — though this remains one of the field’s largest unsolved problems, and the underrepresentation of non-European ancestries in existing GWAS is a structural, not just methodological, limitation.</p>
</section>
<section id="larger-samples-rarer-variants" class="level2" data-number="9.2">
<h2 data-number="9.2" class="anchored" data-anchor-id="larger-samples-rarer-variants"><span class="header-section-number">9.2</span> Larger Samples, Rarer Variants</h2>
<p>Prediction accuracy scales with discovery GWAS sample size. Major biobanks now include roughly: UK Biobank (~500,000 participants), FinnGen (~500,000), the Million Veteran Program (over 1,000,000), and All of Us (targeting over 1,000,000) — with future resources likely to grow substantially larger still.</p>
<p>Most current PRS focus on <strong>common variants</strong>; <strong>rare variants</strong> may carry larger individual biological effects but are harder for standard GWAS to detect reliably, since statistical power drops sharply as allele frequency falls. Integrating common, rare, and structural variation into a single predictive framework is an active research direction.</p>
</section>
<section id="functional-genomics-and-multi-omics" class="level2" data-number="9.3">
<h2 data-number="9.3" class="anchored" data-anchor-id="functional-genomics-and-multi-omics"><span class="header-section-number">9.3</span> Functional Genomics and Multi-Omics</h2>
<p>Beyond the coding/regulatory annotations SBayesRC already uses, future models may incorporate gene expression (eQTLs), chromatin accessibility, single-cell-resolved cell-type-specific effects, and epigenetic marks (DNA methylation, histone modifications) — moving toward genuinely multi-omics prediction. Related approaches like <strong>TWAS</strong> (transcriptome-wide association studies), <strong>PrediXcan</strong>, and <strong>FUSION</strong> predict disease via genetically-predicted gene expression as an intermediate step (SNPs → predicted expression → disease), rather than jumping directly from SNPs to phenotype — potentially yielding more biologically interpretable predictions.</p>
<p><strong>Gene-environment interaction (G×E).</strong> Standard PRS models assume genetic and environmental contributions are additive/independent, but reality is often more complex — a genetic predisposition to obesity, for instance, may be amplified by a high-calorie diet and sedentary lifestyle, or dampened by exercise and healthy nutrition. Modeling these interactions explicitly, rather than assuming independence, is an active area of methods development.</p>
</section>
<section id="machine-learning-and-what-actually-moves-the-needle" class="level2" data-number="9.4">
<h2 data-number="9.4" class="anchored" data-anchor-id="machine-learning-and-what-actually-moves-the-needle"><span class="header-section-number">9.4</span> Machine Learning, and What Actually Moves the Needle</h2>
<p>Neural networks, graph neural networks, transformer architectures, and other deep-learning approaches are being explored for genomic prediction, offering potential to capture nonlinear effects and integrate heterogeneous data types. So far, though, evidence suggests that for most current PRS applications, <strong>better data tends to matter more than more complex models</strong> — larger, more diverse, better-QC’d GWAS typically move prediction accuracy further than swapping in a more sophisticated architecture on the same underlying data.</p>
</section>
<section id="clinical-translation" class="level2" data-number="9.5">
<h2 data-number="9.5" class="anchored" data-anchor-id="clinical-translation"><span class="header-section-number">9.5</span> Clinical Translation</h2>
<p>Potential applications span cardiovascular disease (earlier intervention for high-risk individuals), cancer screening (risk-stratified programs), psychiatry (earlier identification of vulnerable individuals), and preventive medicine generally. Real obstacles to clinical adoption remain: <strong>calibration</strong> (predicted risks must actually match observed outcomes), <strong>equity</strong> (prediction must work reasonably across diverse populations, not just those well-represented in discovery GWAS), <strong>interpretability</strong> (clinicians need understandable, actionable outputs), and <strong>ethics</strong> (privacy and fairness). These are as important to solve as any statistical improvement.</p>
<p>The long-term vision — often called <strong>precision medicine</strong> — combines individual genome, environment, and medical history into personalized healthcare; PRS is likely to become one input among several in that broader picture, not a stand-alone diagnostic tool.</p>
</section>
<section id="how-the-field-got-here" class="level2" data-number="9.6">
<h2 data-number="9.6" class="anchored" data-anchor-id="how-the-field-got-here"><span class="header-section-number">9.6</span> How the Field Got Here</h2>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Era</th>
<th>Approach</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Early</td>
<td>Candidate gene studies</td>
</tr>
<tr class="even">
<td>GWAS era</td>
<td>Single-SNP association analysis</td>
</tr>
<tr class="odd">
<td>PRS era</td>
<td>C+PT</td>
</tr>
<tr class="even">
<td>Whole-genome era</td>
<td>BLUP</td>
</tr>
<tr class="odd">
<td>Bayesian era</td>
<td>BayesR</td>
</tr>
<tr class="even">
<td>Summary-statistics era</td>
<td>SBayesR</td>
</tr>
<tr class="odd">
<td>Functional genomics era</td>
<td>SBayesRC</td>
</tr>
</tbody>
</table>
<p>Each generation incorporated more information and more realistic assumptions about genetic architecture than the last.</p>
<blockquote class="blockquote">
<p><strong>Final key takeaways.</strong> PRS is now central to statistical genetics, and accuracy keeps improving as datasets grow — but multi-ancestry portability, missing heritability, gene-environment interactions, and rare variants remain substantial open problems. Deep learning may help at the margins, but data quality and quantity currently matter more than model sophistication. Clinical implementation requires careful validation on calibration, equity, and interpretability, not just prediction accuracy. Precision medicine — integrating genetics, environment, and clinical data — is a long-term goal the field is still working toward, not a present reality.</p>
</blockquote>


</section>
</section>

 ]]></description>
  <category>Statistical Genetics</category>
  <category>GWAS</category>
  <category>PRS</category>
  <guid>https://bntechie.github.io/tutorials/PRS/Polygenic_Risk_Scores.html</guid>
  <pubDate>Mon, 08 Jun 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/PRS/images/prs-pipeline.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>A Complete GWAS Practical Tutorial Using PLINK, GCTA, R, and METAL</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/GWAS/GWAS.html</link>
  <description><![CDATA[ 




<div class="thesis-hero-wrap">
<p><img src="https://bntechie.github.io/tutorials/GWAS/images/gwas-manhattan.svg" alt="Stylized Manhattan plot illustrating genome-wide association results across chromosomes, with one simulated significant locus" class="thesis-hero-art"></p>
<div class="thesis-hero-caption">
<p>A Manhattan plot: each point is a SNP, plotted by genomic position (x-axis) and significance (y-axis). Towers that cross the genome-wide threshold are the signals a GWAS is built to find.</p>
</div>
</div>
<div class="tag-row">
<p><span class="tag">PLINK</span> <span class="tag">GCTA</span> <span class="tag">METAL</span> <span class="tag">R</span> <span class="tag">Population Genetics</span></p>
</div>
<blockquote class="blockquote">
<p><strong>A note on how to use this tutorial.</strong> PLINK, GCTA, and METAL are external command-line tools – install them separately and run the shown commands against your own genotype files. They are not part of this notebook’s Python kernel and are not executed here. To make the core statistical concepts concrete without requiring real genotype data, several sections include small, genuinely executed Python simulations (clearly marked) that reproduce the <em>shape</em> of the real output – a heterozygosity distribution, a stratified PCA plot, QQ plot patterns, a Manhattan plot, and a GRM heatmap – using synthetic data, not results from the commands above.</p>
</blockquote>
<p>Genome-wide association studies, or GWAS, are used to identify genetic variants associated with traits or diseases.</p>
<p>A GWAS usually tests hundreds of thousands to millions of SNPs across the genome.</p>
<p>For each SNP, we ask:</p>
<blockquote class="blockquote">
<p>Is genetic variation at this SNP statistically associated with the phenotype?</p>
</blockquote>
<p>In this tutorial, we walk through a complete GWAS workflow using:</p>
<ul>
<li>PLINK for genotype quality control</li>
<li>PCA for population structure</li>
<li>GCTA fastGWA for mixed-model association testing</li>
<li>R for QQ plots and Manhattan plots</li>
<li>METAL for meta-analysis</li>
<li>GRM inspection for relatedness checks</li>
</ul>
<p>The goal is not only to run commands, but to understand why each step matters.</p>
<section id="what-you-will-learn" class="level3" data-number="0.0.1">
<h3 data-number="0.0.1" class="anchored" data-anchor-id="what-you-will-learn"><span class="header-section-number">0.0.1</span> What You Will Learn</h3>
<ul>
<li>How to prepare genotype and phenotype files for GWAS</li>
<li>How to perform sample and SNP quality control with PLINK</li>
<li>How to compute principal components and build a GRM</li>
<li>How to run mixed-model GWAS with GCTA fastGWA</li>
<li>How to visualize results with QQ and Manhattan plots</li>
<li>How to perform a simple meta-analysis with METAL</li>
<li>How to inspect relatedness and heterozygosity in GWAS data</li>
</ul>
</section>
<section id="who-should-read-this-tutorial" class="level3" data-number="0.0.2">
<h3 data-number="0.0.2" class="anchored" data-anchor-id="who-should-read-this-tutorial"><span class="header-section-number">0.0.2</span> Who Should Read This Tutorial</h3>
<p>This tutorial is intended for researchers and students who want a practical GWAS workflow using standard tools in statistical genetics. Prior experience with command-line tools, PLINK, and basic genomics concepts is helpful but not required.</p>
</section>
<section id="overview-of-the-gwas-pipeline" class="level3" data-number="0.0.3">
<h3 data-number="0.0.3" class="anchored" data-anchor-id="overview-of-the-gwas-pipeline"><span class="header-section-number">0.0.3</span> Overview of the GWAS Pipeline</h3>
<p>The complete workflow is:</p>
<ol type="1">
<li>Prepare genotype and phenotype files</li>
<li>Perform genotype quality control</li>
<li>Remove low-quality SNPs</li>
<li>Remove low-quality individuals</li>
<li>Check heterozygosity outliers</li>
<li>Compute principal components</li>
<li>Build a genetic relationship matrix</li>
<li>Run GWAS without PC adjustment</li>
<li>Run GWAS with PC adjustment</li>
<li>Compare QQ plots and Manhattan plots</li>
<li>Meta-analyze two GWAS results</li>
<li>Inspect heterogeneity</li>
<li>Identify the top SNP</li>
<li>Inspect relatedness using the GRM</li>
</ol>
</section>
<section id="why-quality-control-is-necessary" class="level3" data-number="0.0.4">
<h3 data-number="0.0.4" class="anchored" data-anchor-id="why-quality-control-is-necessary"><span class="header-section-number">0.0.4</span> Why Quality Control is Necessary?</h3>
<p>Before running GWAS, we must clean the genotype data.</p>
<p>Poor genotype quality can create false associations.</p>
<p>Common problems include:</p>
<ul>
<li>SNPs missing in many individuals</li>
<li>Individuals missing many genotypes</li>
<li>Very rare variants with unstable estimates</li>
<li>SNPs violating Hardy-Weinberg equilibrium</li>
<li>Sample contamination</li>
<li>Inbreeding</li>
<li>Unexpected relatives</li>
<li>Population stratification</li>
</ul>
<p>A GWAS is only as reliable as the data used to run it.</p>
</section>
<section id="data-used-in-this-tutorial" class="level3" data-number="0.0.5">
<h3 data-number="0.0.5" class="anchored" data-anchor-id="data-used-in-this-tutorial"><span class="header-section-number">0.0.5</span> Data Used in This Tutorial</h3>
<p>We assume two simulated studies:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1.bed</span></span>
<span id="cb1-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1.bim</span></span>
<span id="cb1-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1.fam</span></span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study2.bed</span></span>
<span id="cb1-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study2.bim</span></span>
<span id="cb1-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study2.fam</span></span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_pheno.txt</span></span>
<span id="cb1-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study2_pheno.txt</span></span>
<span id="cb1-11"></span>
<span id="cb1-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_covariates.txt</span></span>
<span id="cb1-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study2_covariates.txt</span></span></code></pre></div></div>
<p>Each study contains:</p>
<ul>
<li>around 2,000 individuals</li>
<li>around 50,000 SNPs</li>
<li>one phenotype</li>
<li>covariates including sex, age, and PCs</li>
</ul>
</section>
<section id="plink-file-formats" class="level3" data-number="0.0.6">
<h3 data-number="0.0.6" class="anchored" data-anchor-id="plink-file-formats"><span class="header-section-number">0.0.6</span> PLINK File Formats</h3>
<p>PLINK binary genotype data are stored in three files.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>File</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>.bed</code></td>
<td>Binary genotype data</td>
</tr>
<tr class="even">
<td><code>.bim</code></td>
<td>SNP information</td>
</tr>
<tr class="odd">
<td><code>.fam</code></td>
<td>Individual information</td>
</tr>
</tbody>
</table>
<p>The <code>.bim</code> file contains SNP-level information:</p>
<pre class="text"><code>chromosome  SNP_ID  genetic_distance  base_pair_position  allele1  allele2</code></pre>
<p>The <code>.fam</code> file contains individual-level information:</p>
<pre class="text"><code>FID  IID  father_ID  mother_ID  sex  phenotype</code></pre>
<p>The <code>.bed</code> file stores the actual genotype matrix in compressed binary format.</p>
</section>
<section id="create-working-directory" class="level3" data-number="0.0.7">
<h3 data-number="0.0.7" class="anchored" data-anchor-id="create-working-directory"><span class="header-section-number">0.0.7</span> Create Working Directory</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> GWAS</span>
<span id="cb4-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> GWAS</span>
<span id="cb4-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Place your own study1.{bed,bim,fam}, study2.{bed,bim,fam},</span></span>
<span id="cb4-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># phenotype (study1_pheno.txt, study2_pheno.txt), and</span></span>
<span id="cb4-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># covariate (study1_covariates.txt, study2_covariates.txt) files here.</span></span></code></pre></div></div>
<p>Check files:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ls</span></span></code></pre></div></div>
<p>Inspect the genotype files:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1.fam</span>
<span id="cb6-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1.bim</span></code></pre></div></div>
<p>Inspect phenotype and covariate files:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_pheno.txt</span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_covariates.txt</span></code></pre></div></div>
</section>
<section id="question-is-the-phenotype-quantitative-or-case-control" class="level3" data-number="0.0.8">
<h3 data-number="0.0.8" class="anchored" data-anchor-id="question-is-the-phenotype-quantitative-or-case-control"><span class="header-section-number">0.0.8</span> Question: Is the Phenotype Quantitative or Case-Control?</h3>
<p>Look at the phenotype file:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_pheno.txt</span></code></pre></div></div>
<p>If the phenotype is continuous, such as height, BMI, or simulated trait value, then it is quantitative.</p>
<p>If the phenotype is coded as 0/1 or 1/2 for disease status, then it is case-control.</p>
<p>In this practical, the phenotype is treated as a quantitative phenotype because fastGWA is run using a linear mixed model.</p>
<section id="software-used" class="level4" data-number="0.0.8.1">
<h4 data-number="0.0.8.1" class="anchored" data-anchor-id="software-used"><span class="header-section-number">0.0.8.1</span> Software Used</h4>
<p>We use:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Tool</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>PLINK 1.9</td>
<td>QC and genotype processing</td>
</tr>
<tr class="even">
<td>GCTA</td>
<td>GRM construction and fastGWA</td>
</tr>
<tr class="odd">
<td>R</td>
<td>Plotting and file preparation</td>
</tr>
<tr class="even">
<td>qqman</td>
<td>QQ plots and Manhattan plots</td>
</tr>
<tr class="odd">
<td>METAL</td>
<td>Meta-analysis</td>
</tr>
</tbody>
</table>
</section>
</section>
<section id="part-1-quality-control-in-plink" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Part 1: Quality Control in PLINK</h1>
<p>Quality control is one of the most important parts of GWAS.</p>
<p>The order matters.</p>
<p>We usually clean SNPs first and individuals second.</p>
<p>Why?</p>
<p>If many SNPs are poor quality, individuals may appear to have high missingness just because those SNPs failed. So we first remove bad SNPs, then evaluate individual-level quality.</p>
<section id="step-1.1-get-an-overview-of-the-data" class="level3" data-number="1.0.1">
<h3 data-number="1.0.1" class="anchored" data-anchor-id="step-1.1-get-an-overview-of-the-data"><span class="header-section-number">1.0.1</span> Step 1.1: Get an Overview of the Data</h3>
<p>Run:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--freq</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_freqs</span></code></pre></div></div>
<p>This command:</p>
<ul>
<li>reads <code>study1.bed</code>, <code>study1.bim</code>, and <code>study1.fam</code></li>
<li>reports number of individuals</li>
<li>reports number of SNPs</li>
<li>computes allele frequencies</li>
</ul>
<p>Output files:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_freqs.frq</span></span>
<span id="cb10-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_freqs.log</span></span></code></pre></div></div>
<p>Inspect:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_freqs.frq</span></code></pre></div></div>
<p>The <code>.frq</code> file contains allele frequency information.</p>
<p>Important columns usually include:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Column</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>CHR</td>
<td>Chromosome</td>
</tr>
<tr class="even">
<td>SNP</td>
<td>SNP ID</td>
</tr>
<tr class="odd">
<td>A1</td>
<td>Allele 1</td>
</tr>
<tr class="even">
<td>A2</td>
<td>Allele 2</td>
</tr>
<tr class="odd">
<td>MAF</td>
<td>Minor allele frequency</td>
</tr>
<tr class="even">
<td>NCHROBS</td>
<td>Number of observed chromosomes</td>
</tr>
</tbody>
</table>
</section>
<section id="step-1.2-snp-missingness" class="level3" data-number="1.0.2">
<h3 data-number="1.0.2" class="anchored" data-anchor-id="step-1.2-snp-missingness"><span class="header-section-number">1.0.2</span> Step 1.2: SNP Missingness</h3>
<p>Some SNPs fail genotyping in many individuals.</p>
<p>This is measured by SNP missingness.</p>
<p>Run:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb12-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--missing</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_miss</span></code></pre></div></div>
<p>This creates:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb13-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_miss.imiss</span></span>
<span id="cb13-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_miss.lmiss</span></span></code></pre></div></div>
<table class="caption-top table">
<thead>
<tr class="header">
<th>File</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>.imiss</code></td>
<td>Missingness per individual</td>
</tr>
<tr class="even">
<td><code>.lmiss</code></td>
<td>Missingness per SNP</td>
</tr>
</tbody>
</table>
<p>Inspect SNP missingness:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_miss.lmiss</span></code></pre></div></div>
<p>The important column is:</p>
<pre class="text"><code>F_MISS</code></pre>
<p>If:</p>
<pre class="text"><code>F_MISS = 0.05</code></pre>
<p>then the SNP is missing in 5% of individuals.</p>
</section>
<section id="remove-snps-with-missingness-2" class="level3" data-number="1.0.3">
<h3 data-number="1.0.3" class="anchored" data-anchor-id="remove-snps-with-missingness-2"><span class="header-section-number">1.0.3</span> Remove SNPs With Missingness &gt; 2%</h3>
<p>We keep SNPs with call rate at least 98%.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb17-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb17-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--geno</span> 0.02 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb17-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb17-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_geno</span></code></pre></div></div>
<p>Explanation:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Flag</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>--bfile study1</code></td>
<td>Input PLINK binary dataset</td>
</tr>
<tr class="even">
<td><code>--geno 0.02</code></td>
<td>Remove SNPs missing in more than 2% of individuals</td>
</tr>
<tr class="odd">
<td><code>--make-bed</code></td>
<td>Write new PLINK binary files</td>
</tr>
<tr class="even">
<td><code>--out study1_geno</code></td>
<td>Output prefix</td>
</tr>
</tbody>
</table>
<p>Output:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb18-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_geno.bed</span></span>
<span id="cb18-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_geno.bim</span></span>
<span id="cb18-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_geno.fam</span></span></code></pre></div></div>
</section>
<section id="step-1.3-minor-allele-frequency-filtering" class="level3" data-number="1.0.4">
<h3 data-number="1.0.4" class="anchored" data-anchor-id="step-1.3-minor-allele-frequency-filtering"><span class="header-section-number">1.0.4</span> Step 1.3: Minor Allele Frequency Filtering</h3>
<p>Minor allele frequency, or MAF, is the frequency of the less common allele.</p>
<p>Rare SNPs are difficult to test in small samples because:</p>
<ul>
<li>there are few minor allele carriers</li>
<li>standard errors become large</li>
<li>genotype errors can have large influence</li>
<li>power is low</li>
</ul>
<p>We remove SNPs with MAF below 1%.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb19-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_geno <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb19-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--maf</span> 0.01 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb19-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb19-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_maf</span></code></pre></div></div>
<p>This removes SNPs with:</p>
<pre class="text"><code>MAF &lt; 0.01</code></pre>
</section>
<section id="should-the-maf-threshold-change-in-a-larger-study" class="level2" data-number="1.1">
<h2 data-number="1.1" class="anchored" data-anchor-id="should-the-maf-threshold-change-in-a-larger-study"><span class="header-section-number">1.1</span> Should the MAF Threshold Change in a Larger Study?</h2>
<p>Yes, possibly.</p>
<p>In a much larger sample, such as 100,000 or 500,000 individuals, we may have enough power to analyze rarer variants.</p>
<p>For example:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Sample Size</th>
<th>Reasonable MAF threshold</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>2,000</td>
<td>1% or 5%</td>
</tr>
<tr class="even">
<td>50,000</td>
<td>0.5% or 1%</td>
</tr>
<tr class="odd">
<td>500,000</td>
<td>0.1% may be possible</td>
</tr>
</tbody>
</table>
<p>However, rare variant analysis often requires additional care, such as burden tests or sequence-level QC.</p>
<section id="step-1.4-hardy-weinberg-equilibrium" class="level3" data-number="1.1.1">
<h3 data-number="1.1.1" class="anchored" data-anchor-id="step-1.4-hardy-weinberg-equilibrium"><span class="header-section-number">1.1.1</span> Step 1.4: Hardy-Weinberg Equilibrium</h3>
<p>Hardy-Weinberg equilibrium gives expected genotype frequencies under random mating.</p>
<p>For allele frequency:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap%0A"></p>
<p>the expected genotype frequencies are:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap%5E2%0A"></p>
<p><img src="https://latex.codecogs.com/png.latex?%0A2p(1-p)%0A"></p>
<p><img src="https://latex.codecogs.com/png.latex?%0A(1-p)%5E2%0A"></p>
<p>Strong deviation from HWE can indicate:</p>
<ul>
<li>genotyping error</li>
<li>population stratification</li>
<li>inbreeding</li>
<li>selection</li>
<li>true disease association in case-control data</li>
</ul>
<p>Remove SNPs with HWE p-value below:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A1%20%5Ctimes%2010%5E%7B-6%7D%0A"></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb21-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_maf <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb21-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--hwe</span> 1e-6 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb21-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb21-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_qc_snps</span></code></pre></div></div>
</section>
</section>
<section id="why-test-hwe-only-in-controls-for-case-control-studies" class="level2" data-number="1.2">
<h2 data-number="1.2" class="anchored" data-anchor-id="why-test-hwe-only-in-controls-for-case-control-studies"><span class="header-section-number">1.2</span> Why Test HWE Only in Controls for Case-Control Studies?</h2>
<p>In case-control studies, a truly disease-associated SNP may deviate from HWE among cases.</p>
<p>If we test HWE in all individuals or in cases, we may accidentally remove true disease signals.</p>
<p>Therefore, for case-control GWAS, HWE filtering is often performed in controls only.</p>
<section id="step-1.5-individual-missingness" class="level3" data-number="1.2.1">
<h3 data-number="1.2.1" class="anchored" data-anchor-id="step-1.5-individual-missingness"><span class="header-section-number">1.2.1</span> Step 1.5: Individual Missingness</h3>
<p>After SNP QC, we check missingness per individual.</p>
<p>Some individuals may have poor DNA quality and many missing genotypes.</p>
<p>Remove individuals missing more than 2% of genotypes:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb22-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc_snps <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--mind</span> 0.02 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb22-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_qc_mind</span></code></pre></div></div>
<p>Explanation:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Flag</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>--mind 0.02</code></td>
<td>Remove individuals with missingness &gt; 2%</td>
</tr>
</tbody>
</table>
</section>
<section id="step-1.6-heterozygosity-check" class="level3" data-number="1.2.2">
<h3 data-number="1.2.2" class="anchored" data-anchor-id="step-1.6-heterozygosity-check"><span class="header-section-number">1.2.2</span> Step 1.6: Heterozygosity Check</h3>
<p>Heterozygosity is the proportion of SNPs where an individual carries two different alleles.</p>
<p>Individuals with unusually high heterozygosity may indicate:</p>
<ul>
<li>sample contamination</li>
<li>DNA mixture</li>
<li>technical artifacts</li>
</ul>
<p>Individuals with unusually low heterozygosity may indicate:</p>
<ul>
<li>inbreeding</li>
<li>long runs of homozygosity</li>
<li>poor genotype calling</li>
</ul>
<p>Compute heterozygosity:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb23-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc_mind <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb23-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--het</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb23-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_het</span></code></pre></div></div>
<p>Inspect:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb24-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_het.het</span></code></pre></div></div>
<p>Important columns:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Column</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>O(HOM)</td>
<td>Observed homozygous genotypes</td>
</tr>
<tr class="even">
<td>E(HOM)</td>
<td>Expected homozygous genotypes</td>
</tr>
<tr class="odd">
<td>N(NM)</td>
<td>Number of non-missing genotypes</td>
</tr>
<tr class="even">
<td>F</td>
<td>Inbreeding coefficient estimate</td>
</tr>
</tbody>
</table>
</section>
</section>
</section>
<section id="plot-heterozygosity-in-r" class="level1" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Plot Heterozygosity in R</h1>
<p>Switch to R.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb25-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setwd</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"YOUR_WORKING_DIRECTORY"</span>)</span>
<span id="cb25-2"></span>
<span id="cb25-3">het <span class="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.table</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_het.het"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb25-4"></span>
<span id="cb25-5">het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>N.NM. <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>O.HOM.) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>N.NM.</span>
<span id="cb25-6"></span>
<span id="cb25-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hist</span>(</span>
<span id="cb25-8">  het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate,</span>
<span id="cb25-9">  <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;">50</span>,</span>
<span id="cb25-10">  <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;">"Heterozygosity Rate"</span>,</span>
<span id="cb25-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heterozygosity"</span></span>
<span id="cb25-12">)</span>
<span id="cb25-13"></span>
<span id="cb25-14">upper <span class="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>(het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate) <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> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd</span>(het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate)</span>
<span id="cb25-15">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;">mean</span>(het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate) <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> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd</span>(het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate)</span>
<span id="cb25-16"></span>
<span id="cb25-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">v =</span> upper, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb25-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">v =</span> lower, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
</section>
<section id="identify-heterozygosity-outliers" class="level1" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> Identify Heterozygosity Outliers</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb26-1">outliers <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> het[</span>
<span id="cb26-2">  het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> lower <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> het<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> upper,</span>
<span id="cb26-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;">"FID"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"IID"</span>)</span>
<span id="cb26-4">]</span>
<span id="cb26-5"></span>
<span id="cb26-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heterozygosity outliers:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(outliers), <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>)</span>
<span id="cb26-7"></span>
<span id="cb26-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write.table</span>(</span>
<span id="cb26-9">  outliers,</span>
<span id="cb26-10">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_het_outliers.txt"</span>,</span>
<span id="cb26-11">  <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;">FALSE</span>,</span>
<span id="cb26-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb26-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quote =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb26-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</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;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb26-15">)</span></code></pre></div></div>
</section>
<section id="remove-heterozygosity-outliers" class="level1" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> Remove Heterozygosity Outliers</h1>
<p>Back in the terminal:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb27-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc_mind <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb27-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--remove</span> study1_het_outliers.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb27-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb27-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_qc</span></code></pre></div></div>
<p>Now <code>study1_qc</code> is the final QC’d Study 1 dataset.</p>
</section>
<section id="step-1.7-summarize-qc-results" class="level1" data-number="5">
<h1 data-number="5"><span class="header-section-number">5</span> Step 1.7: Summarize QC Results</h1>
<p>Check final SNP and individual counts:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb28-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--freq</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb28-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_qc_freqs</span></code></pre></div></div>
<p>You should summarize:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th>QC Step</th>
<th>Output Prefix</th>
<th>What Was Removed</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Raw data</td>
<td>study1</td>
<td>None</td>
</tr>
<tr class="even">
<td>SNP missingness</td>
<td>study1_geno</td>
<td>SNPs with missingness &gt; 2%</td>
</tr>
<tr class="odd">
<td>MAF filter</td>
<td>study1_maf</td>
<td>SNPs with MAF &lt; 1%</td>
</tr>
<tr class="even">
<td>HWE filter</td>
<td>study1_qc_snps</td>
<td>SNPs with HWE p &lt; 1e-6</td>
</tr>
<tr class="odd">
<td>Individual missingness</td>
<td>study1_qc_mind</td>
<td>Individuals with missingness &gt; 2%</td>
</tr>
<tr class="even">
<td>Heterozygosity</td>
<td>study1_qc</td>
<td>Heterozygosity outliers</td>
</tr>
</tbody>
</table>
</section>
<section id="repeat-qc-for-study-2" class="level1" data-number="6">
<h1 data-number="6"><span class="header-section-number">6</span> Repeat QC for Study 2</h1>
<p>Now repeat the same commands for Study 2.</p>
</section>
<section id="study-2-overview" class="level1" data-number="7">
<h1 data-number="7"><span class="header-section-number">7</span> Study 2: Overview</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb29-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--freq</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_freqs</span></code></pre></div></div>
</section>
<section id="study-2-snp-missingness" class="level1" data-number="8">
<h1 data-number="8"><span class="header-section-number">8</span> Study 2: SNP Missingness</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb30-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--missing</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_miss</span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb31-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study2_miss.lmiss</span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb32-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb32-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--geno</span> 0.02 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb32-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb32-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_geno</span></code></pre></div></div>
</section>
<section id="study-2-maf-filtering" class="level1" data-number="9">
<h1 data-number="9"><span class="header-section-number">9</span> Study 2: MAF Filtering</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb33-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2_geno <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb33-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--maf</span> 0.01 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb33-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb33-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_maf</span></code></pre></div></div>
</section>
<section id="study-2-hwe-filtering" class="level1" data-number="10">
<h1 data-number="10"><span class="header-section-number">10</span> Study 2: HWE Filtering</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb34-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2_maf <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb34-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--hwe</span> 1e-6 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb34-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb34-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_qc_snps</span></code></pre></div></div>
</section>
<section id="study-2-individual-missingness" class="level1" data-number="11">
<h1 data-number="11"><span class="header-section-number">11</span> Study 2: Individual Missingness</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb35-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2_qc_snps <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb35-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--mind</span> 0.02 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb35-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb35-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_qc_mind</span></code></pre></div></div>
</section>
<section id="study-2-heterozygosity" class="level1" data-number="12">
<h1 data-number="12"><span class="header-section-number">12</span> Study 2: Heterozygosity</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb36" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb36-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2_qc_mind <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb36-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--het</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb36-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_het</span></code></pre></div></div>
<p>In R:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb37" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb37-1">het2 <span class="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.table</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study2_het.het"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb37-2"></span>
<span id="cb37-3">het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>N.NM. <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>O.HOM.) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>N.NM.</span>
<span id="cb37-4"></span>
<span id="cb37-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hist</span>(</span>
<span id="cb37-6">  het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate,</span>
<span id="cb37-7">  <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;">50</span>,</span>
<span id="cb37-8">  <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;">"Study 2 Heterozygosity Rate"</span>,</span>
<span id="cb37-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heterozygosity"</span></span>
<span id="cb37-10">)</span>
<span id="cb37-11"></span>
<span id="cb37-12">upper2 <span class="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>(het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate) <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> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd</span>(het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate)</span>
<span id="cb37-13">lower2 <span class="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>(het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate) <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> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd</span>(het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate)</span>
<span id="cb37-14"></span>
<span id="cb37-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">v =</span> upper2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb37-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">v =</span> lower2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lty =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb37-17"></span>
<span id="cb37-18">outliers2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> het2[</span>
<span id="cb37-19">  het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> lower2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> het2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>het_rate <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> upper2,</span>
<span id="cb37-20">  <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;">"FID"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"IID"</span>)</span>
<span id="cb37-21">]</span>
<span id="cb37-22"></span>
<span id="cb37-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Study 2 heterozygosity outliers:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(outliers2), <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>)</span>
<span id="cb37-24"></span>
<span id="cb37-25"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write.table</span>(</span>
<span id="cb37-26">  outliers2,</span>
<span id="cb37-27">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study2_het_outliers.txt"</span>,</span>
<span id="cb37-28">  <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;">FALSE</span>,</span>
<span id="cb37-29">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb37-30">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quote =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb37-31">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</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;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb37-32">)</span></code></pre></div></div>
<p>Back in terminal:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb38" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb38-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2_qc_mind <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb38-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--remove</span> study2_het_outliers.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb38-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb38-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_qc</span></code></pre></div></div>
<p>Check final Study 2 data:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb39" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb39-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb39-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--freq</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb39-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_qc_freqs</span></code></pre></div></div>
<div id="f165144d-ed38-41fd-8896-33a60e65b1d4" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:18:33.442388Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:18:33.442219Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:18:34.080173Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:18:34.078949Z&quot;}}" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb40" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb40-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Illustrative simulation -- NOT real output from the commands above.</span></span>
<span id="cb40-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Reproduces the shape of a typical study1_het.het heterozygosity distribution</span></span>
<span id="cb40-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># and the +/- 3 SD outlier rule described in the text.</span></span>
<span id="cb40-4"></span>
<span id="cb40-5"><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="cb40-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb40-7"></span>
<span id="cb40-8">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;">42</span>)</span>
<span id="cb40-9"></span>
<span id="cb40-10">n <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>
<span id="cb40-11">het_rate <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.30</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.02</span>, n)</span>
<span id="cb40-12">outlier_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.choice(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, replace<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="cb40-13">het_rate[outlier_idx] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> rng.choice([<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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> rng.uniform(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.08</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>)</span>
<span id="cb40-14"></span>
<span id="cb40-15">mean_h, sd_h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> het_rate.mean(), het_rate.std()</span>
<span id="cb40-16">upper, lower <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mean_h <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;">3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> sd_h, mean_h <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;">3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> sd_h</span>
<span id="cb40-17">outliers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.where((het_rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> upper) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> (het_rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> lower))[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb40-18"></span>
<span id="cb40-19">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<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;">7</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.2</span>))</span>
<span id="cb40-20">ax.hist(het_rate, bins<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;">50</span>, color<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;">"#2f6f6b"</span>, 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.75</span>, edgecolor<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;">"#fbfaf7"</span>)</span>
<span id="cb40-21">ax.axvline(upper, color<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;">"#b9812c"</span>, linestyle<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;">"--"</span>, linewidth<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.6</span>)</span>
<span id="cb40-22">ax.axvline(lower, color<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;">"#b9812c"</span>, linestyle<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;">"--"</span>, linewidth<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.6</span>)</span>
<span id="cb40-23">ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heterozygosity Rate Across Individuals (Simulated)"</span>)</span>
<span id="cb40-24">ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heterozygosity rate"</span>)</span>
<span id="cb40-25">ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of individuals"</span>)</span>
<span id="cb40-26">plt.tight_layout()</span>
<span id="cb40-27">plt.show()</span>
<span id="cb40-28"></span>
<span id="cb40-29"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Flagged </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(outliers)<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;"> heterozygosity outliers out of </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="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> individuals"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/GWAS/GWAS_files/figure-html/cell-2-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Flagged 15 heterozygosity outliers out of 2000 individuals</code></pre>
</div>
</div>
<section id="qc-interpretation" class="level3" data-number="12.0.1">
<h3 data-number="12.0.1" class="anchored" data-anchor-id="qc-interpretation"><span class="header-section-number">12.0.1</span> QC Interpretation</h3>
<p>At the end of QC, we should ask:</p>
<ol type="1">
<li>How many SNPs were removed due to missingness?</li>
<li>How many SNPs were removed due to low MAF?</li>
<li>How many SNPs were removed due to HWE deviation?</li>
<li>How many individuals were removed due to missingness?</li>
<li>How many individuals were removed due to heterozygosity outliers?</li>
<li>Are the remaining sample sizes reasonable?</li>
<li>Are the remaining SNP counts reasonable?</li>
</ol>
</section>
<section id="why-this-qc-pipeline-matters" class="level3" data-number="12.0.2">
<h3 data-number="12.0.2" class="anchored" data-anchor-id="why-this-qc-pipeline-matters"><span class="header-section-number">12.0.2</span> Why This QC Pipeline Matters</h3>
<p>Skipping SNP missingness filtering can leave unreliable variants.</p>
<p>Skipping MAF filtering can produce unstable rare-variant tests.</p>
<p>Skipping HWE filtering can leave genotyping artifacts.</p>
<p>Skipping individual missingness filtering can leave poor-quality samples.</p>
<p>Skipping heterozygosity checks can leave contaminated or inbred samples.</p>
<p>In GWAS, even small QC problems can create genome-wide false positives.</p>
</section>
<section id="end-of-part-1" class="level3" data-number="12.0.3">
<h3 data-number="12.0.3" class="anchored" data-anchor-id="end-of-part-1"><span class="header-section-number">12.0.3</span> End of Part 1</h3>
<p>At this point we have:</p>
<ul>
<li>inspected genotype files</li>
<li>computed allele frequencies</li>
<li>removed poorly genotyped SNPs</li>
<li>removed rare variants</li>
<li>removed HWE outliers</li>
<li>removed low-quality individuals</li>
<li>removed heterozygosity outliers</li>
<li>produced final QC’d datasets:</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb42" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb42-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_qc</span></span>
<span id="cb42-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study2_qc</span></span></code></pre></div></div>
<p>Next we will compute principal components to detect and correct population structure.</p>
</section>
<section id="part-2-principal-components-analysis-pca-and-population-stratification" class="level2" data-number="12.1">
<h2 data-number="12.1" class="anchored" data-anchor-id="part-2-principal-components-analysis-pca-and-population-stratification"><span class="header-section-number">12.1</span> Part 2: Principal Components Analysis (PCA) and Population Stratification</h2>
<section id="why-do-we-need-pca" class="level4" data-number="12.1.0.1">
<h4 data-number="12.1.0.1" class="anchored" data-anchor-id="why-do-we-need-pca"><span class="header-section-number">12.1.0.1</span> Why Do We Need PCA?</h4>
<p>Suppose we perform a GWAS for a disease.</p>
<p>Imagine:</p>
<ul>
<li>Group A has ancestry from Northern Europe</li>
<li>Group B has ancestry from Southern Europe</li>
</ul>
<p>Now suppose:</p>
<ul>
<li>Disease prevalence differs between groups</li>
<li>Allele frequencies differ between groups</li>
</ul>
<p>A SNP can appear associated with disease simply because ancestry differs.</p>
<p>This creates a false positive association.</p>
<p>This phenomenon is called:</p>
</section>
<section id="population-stratification" class="level3" data-number="12.1.1">
<h3 data-number="12.1.1" class="anchored" data-anchor-id="population-stratification"><span class="header-section-number">12.1.1</span> Population Stratification</h3>
<p>Population stratification is one of the largest sources of false positives in GWAS.</p>
<p>A GWAS can produce apparently significant associations even when no causal effect exists.</p>
<section id="example" class="level4" data-number="12.1.1.1">
<h4 data-number="12.1.1.1" class="anchored" data-anchor-id="example"><span class="header-section-number">12.1.1.1</span> Example</h4>
<p>Suppose:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Population</th>
<th>Disease Rate</th>
<th>Allele Frequency</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Population A</td>
<td>10%</td>
<td>0.20</td>
</tr>
<tr class="even">
<td>Population B</td>
<td>40%</td>
<td>0.80</td>
</tr>
</tbody>
</table>
<p>Even if the SNP has nothing to do with disease:</p>
<ul>
<li>cases contain more individuals from Population B</li>
<li>controls contain more individuals from Population A</li>
</ul>
<p>The SNP becomes associated with disease.</p>
<p>The association is completely spurious.</p>
</section>
</section>
</section>
</section>
<section id="how-pca-helps" class="level1" data-number="13">
<h1 data-number="13"><span class="header-section-number">13</span> How PCA Helps</h1>
<p>Principal Components Analysis identifies major axes of genetic variation.</p>
<p>Instead of looking at:</p>
<pre class="text"><code>50,000 SNPs</code></pre>
<p>we summarize ancestry using:</p>
<pre class="text"><code>PC1
PC2
PC3
...
PC10</code></pre>
<p>These PCs can then be included as covariates in the GWAS model.</p>
<p>The PCs absorb ancestry differences.</p>
<p>This dramatically reduces false positives.</p>
</section>
<section id="mathematical-intuition" class="level1" data-number="14">
<h1 data-number="14"><span class="header-section-number">14</span> Mathematical Intuition</h1>
<p>Suppose our genotype matrix is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AX%0A"></p>
<p>with dimensions:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%20%5Ctimes%20M%0A"></p>
<p>where:</p>
<ul>
<li>N = individuals</li>
<li>M = SNPs</li>
</ul>
<p>For example:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A2000%20%5Ctimes%2050000%0A"></p>
<p>PCA decomposes the genotype matrix into orthogonal directions of variation.</p>
<p>Mathematically:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AX%20=%20UDV%5ET%0A"></p>
<p>where:</p>
<ul>
<li>U contains individual scores</li>
<li>D contains singular values</li>
<li>V contains SNP loadings</li>
</ul>
<p>The first principal component captures the largest source of genetic variation.</p>
<p>Often:</p>
<ul>
<li>PC1 reflects ancestry</li>
<li>PC2 reflects ancestry</li>
<li>PC3 reflects finer population structure</li>
</ul>
<div id="794137b4-c176-4465-b03c-84e8b818c890" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:18:34.082300Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:18:34.082050Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:18:35.751224Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:18:35.749866Z&quot;}}" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb45" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb45-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Illustrative simulation -- NOT real output from PLINK --pca.</span></span>
<span id="cb45-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulates genotypes for two diverged populations plus an admixed group,</span></span>
<span id="cb45-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># to make the "How PCA Helps" discussion above concrete.</span></span>
<span id="cb45-4"></span>
<span id="cb45-5"><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="cb45-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb45-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.decomposition <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PCA</span>
<span id="cb45-8"></span>
<span id="cb45-9">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;">42</span>)</span>
<span id="cb45-10">n_per_group, n_snps <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;">300</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span></span>
<span id="cb45-11"></span>
<span id="cb45-12"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> simulate_genotypes(n_ind, n_snps, allele_freqs):</span>
<span id="cb45-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> rng.binomial(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, allele_freqs, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(n_ind, n_snps))</span>
<span id="cb45-14"></span>
<span id="cb45-15">freqs_pop_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.uniform(<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.5</span>, n_snps)</span>
<span id="cb45-16">freqs_pop_b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.clip(freqs_pop_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> rng.normal(<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>, n_snps), <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.99</span>)</span>
<span id="cb45-17">freqs_admixed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (freqs_pop_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> freqs_pop_b) <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>
<span id="cb45-18"></span>
<span id="cb45-19">geno_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_genotypes(n_per_group, n_snps, freqs_pop_a)</span>
<span id="cb45-20">geno_b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_genotypes(n_per_group, n_snps, freqs_pop_b)</span>
<span id="cb45-21">geno_admixed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_genotypes(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>, n_snps, freqs_admixed)</span>
<span id="cb45-22"></span>
<span id="cb45-23">geno <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.vstack([geno_a, geno_b, geno_admixed])</span>
<span id="cb45-24">labels <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;">"Population A"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_per_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;">"Population B"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_per_group <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb45-25">          [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Admixed"</span>] <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;">150</span>)</span>
<span id="cb45-26"></span>
<span id="cb45-27">geno_std <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (geno <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> geno.mean(axis<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 class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (geno.std(axis<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 class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-8</span>)</span>
<span id="cb45-28">pcs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PCA(n_components<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>).fit_transform(geno_std)</span>
<span id="cb45-29"></span>
<span id="cb45-30">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<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;">6.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5.5</span>))</span>
<span id="cb45-31">colors <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;">"Population A"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6f6b"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Population B"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b9812c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Admixed"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#4a5a68"</span>}</span>
<span id="cb45-32"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> grp <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Population A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Population B"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Admixed"</span>]:</span>
<span id="cb45-33">    mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array(labels) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> grp</span>
<span id="cb45-34">    ax.scatter(pcs[mask, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], pcs[mask, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], s<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;">18</span>, 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.7</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>colors[grp], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>grp)</span>
<span id="cb45-35">ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PCA on Simulated Genotypes: Population Stratification"</span>)</span>
<span id="cb45-36">ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC1"</span>)</span>
<span id="cb45-37">ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC2"</span>)</span>
<span id="cb45-38">ax.legend(frameon<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="cb45-39">plt.tight_layout()</span>
<span id="cb45-40">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/GWAS/GWAS_files/figure-html/cell-3-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="why-ld-pruning-is-necessary" class="level1" data-number="15">
<h1 data-number="15"><span class="header-section-number">15</span> Why LD Pruning is Necessary</h1>
<p>Before PCA we must remove highly correlated SNPs.</p>
<p>Otherwise:</p>
<ul>
<li>large LD blocks dominate the PCA</li>
<li>certain chromosomes become overrepresented</li>
<li>ancestry signals become distorted</li>
</ul>
<p>Therefore we first perform:</p>
<section id="ld-pruning" class="level2" data-number="15.1">
<h2 data-number="15.1" class="anchored" data-anchor-id="ld-pruning"><span class="header-section-number">15.1</span> LD Pruning</h2>
</section>
</section>
<section id="linkage-disequilibrium-refresher" class="level1" data-number="16">
<h1 data-number="16"><span class="header-section-number">16</span> Linkage Disequilibrium Refresher</h1>
<p>Linkage disequilibrium (LD) measures correlation between nearby SNPs.</p>
<p>For two SNPs:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ar%5E2%0A"></p>
<p>measures their correlation.</p>
<p>Values:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>r²</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>Independent</td>
</tr>
<tr class="even">
<td>1</td>
<td>Perfect correlation</td>
</tr>
</tbody>
</table>
<p>PCA works best when SNPs are approximately independent.</p>
</section>
<section id="step-2.1-ld-pruning" class="level1" data-number="17">
<h1 data-number="17"><span class="header-section-number">17</span> Step 2.1 LD Pruning</h1>
<p>Run:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb46" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb46-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb46-2">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--indep-pairwise</span> 50 5 0.2 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb46-3">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_prune</span></code></pre></div></div>
</section>
<section id="understanding-the-command" class="level1" data-number="18">
<h1 data-number="18"><span class="header-section-number">18</span> Understanding the Command</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb47" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb47-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">--indep-pairwise</span> 50 5 0.2</span></code></pre></div></div>
<p>means:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Parameter</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>50</td>
<td>Window size</td>
</tr>
<tr class="even">
<td>5</td>
<td>Step size</td>
</tr>
<tr class="odd">
<td>0.2</td>
<td>r² threshold</td>
</tr>
</tbody>
</table>
<p>PLINK:</p>
<ol type="1">
<li>examines 50 SNP windows</li>
<li>shifts by 5 SNPs</li>
<li>removes SNPs with:</li>
</ol>
<p><img src="https://latex.codecogs.com/png.latex?%0Ar%5E2%20%3E%200.2%0A"></p>
</section>
<section id="output-files" class="level1" data-number="19">
<h1 data-number="19"><span class="header-section-number">19</span> Output Files</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb48" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb48-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_prune.prune.in</span></span>
<span id="cb48-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_prune.prune.out</span></span></code></pre></div></div>
<section id="snps-retained" class="level3" data-number="19.0.1">
<h3 data-number="19.0.1" class="anchored" data-anchor-id="snps-retained"><span class="header-section-number">19.0.1</span> SNPs Retained</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb49" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb49-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wc</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> study1_prune.prune.in</span></code></pre></div></div>
<p>These SNPs will be used for PCA.</p>
</section>
<section id="snps-removed" class="level3" data-number="19.0.2">
<h3 data-number="19.0.2" class="anchored" data-anchor-id="snps-removed"><span class="header-section-number">19.0.2</span> SNPs Removed</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb50" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb50-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wc</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> study1_prune.prune.out</span></code></pre></div></div>
<p>These SNPs were excluded because of LD.</p>
</section>
</section>
<section id="why-not-use-all-snps" class="level1" data-number="20">
<h1 data-number="20"><span class="header-section-number">20</span> Why Not Use All SNPs?</h1>
<p>Imagine a chromosome region containing:</p>
<pre class="text"><code>500 highly correlated SNPs</code></pre>
<p>Without pruning:</p>
<ul>
<li>that region contributes 500 times</li>
<li>another region contributes only once</li>
</ul>
<p>The PCA becomes biased.</p>
<p>LD pruning gives each genomic region approximately equal influence.</p>
</section>
<section id="step-2.2-compute-principal-components" class="level1" data-number="21">
<h1 data-number="21"><span class="header-section-number">21</span> Step 2.2 Compute Principal Components</h1>
<p>Now compute PCs using only pruned SNPs.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb52" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb52-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb52-2">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--extract</span> study1_prune.prune.in <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb52-3">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pca</span> 10 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb52-4">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_pca</span></code></pre></div></div>
</section>
<section id="output-files-1" class="level1" data-number="22">
<h1 data-number="22"><span class="header-section-number">22</span> Output Files</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb53" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb53-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_pca.eigenvec</span></span>
<span id="cb53-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_pca.eigenval</span></span></code></pre></div></div>
<p>The eigenvectors contain PC scores.</p>
<p>Inspect:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb54" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb54-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_pca.eigenvec</span></code></pre></div></div>
<p>Example:</p>
<pre class="text"><code>FID IID PC1 PC2 PC3 ...</code></pre>
<p>Each row represents one individual.</p>
<section id="variance-explained" class="level3" data-number="22.0.1">
<h3 data-number="22.0.1" class="anchored" data-anchor-id="variance-explained"><span class="header-section-number">22.0.1</span> Variance Explained</h3>
<p>Inspect:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb56" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb56-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span> study1_pca.eigenval</span></code></pre></div></div>
<p>The first eigenvalue corresponds to:</p>
<pre class="text"><code>PC1</code></pre>
<p>The second eigenvalue corresponds to:</p>
<pre class="text"><code>PC2</code></pre>
<p>Larger eigenvalues indicate stronger axes of variation.</p>
<section id="visualizing-principal-components" class="level4" data-number="22.0.1.1">
<h4 data-number="22.0.1.1" class="anchored" data-anchor-id="visualizing-principal-components"><span class="header-section-number">22.0.1.1</span> Visualizing Principal Components</h4>
<p>Switch to R.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb59" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb59-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;">read.table</span>(</span>
<span id="cb59-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_pca.eigenvec"</span>,</span>
<span id="cb59-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb59-4">)</span>
<span id="cb59-5"></span>
<span id="cb59-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(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;">c</span>(</span>
<span id="cb59-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FID"</span>,</span>
<span id="cb59-8">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"IID"</span>,</span>
<span id="cb59-9">  <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;">"PC"</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;">10</span>)</span>
<span id="cb59-10">)</span></code></pre></div></div>
</section>
</section>
</section>
<section id="pc1-vs-pc2" class="level1" data-number="23">
<h1 data-number="23"><span class="header-section-number">23</span> PC1 vs PC2</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb60" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb60-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb60-2">  pcs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PC1,</span>
<span id="cb60-3">  pcs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PC2,</span>
<span id="cb60-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC1"</span>,</span>
<span id="cb60-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC2"</span>,</span>
<span id="cb60-6">  <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;">"Study 1: PC1 vs PC2"</span>,</span>
<span id="cb60-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb60-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"steelblue"</span></span>
<span id="cb60-9">)</span></code></pre></div></div>
</section>
<section id="interpretation" class="level1" data-number="24">
<h1 data-number="24"><span class="header-section-number">24</span> Interpretation</h1>
<p>Each point is one individual.</p>
<p>Individuals close together are genetically similar.</p>
<p>Individuals far apart are genetically different.</p>
</section>
<section id="possible-outcomes" class="level1" data-number="25">
<h1 data-number="25"><span class="header-section-number">25</span> Possible Outcomes</h1>
<section id="scenario-1-single-cloud" class="level2" data-number="25.1">
<h2 data-number="25.1" class="anchored" data-anchor-id="scenario-1-single-cloud"><span class="header-section-number">25.1</span> Scenario 1: Single Cloud</h2>
<pre class="text"><code>*******
*********
*******</code></pre>
<p>Interpretation:</p>
<ul>
<li>relatively homogeneous population</li>
<li>little population structure</li>
</ul>
</section>
<section id="scenario-2-two-clusters" class="level2" data-number="25.2">
<h2 data-number="25.2" class="anchored" data-anchor-id="scenario-2-two-clusters"><span class="header-section-number">25.2</span> Scenario 2: Two Clusters</h2>
<pre class="text"><code>****      ****
****      ****</code></pre>
<p>Interpretation:</p>
<ul>
<li>two ancestry groups</li>
<li>strong population stratification</li>
</ul>
</section>
<section id="scenario-3-gradient" class="level2" data-number="25.3">
<h2 data-number="25.3" class="anchored" data-anchor-id="scenario-3-gradient"><span class="header-section-number">25.3</span> Scenario 3: Gradient</h2>
<pre class="text"><code>****
  ****
      ****</code></pre>
<p>Interpretation:</p>
<ul>
<li>continuous ancestry variation</li>
<li>admixture</li>
</ul>
<section id="real-example" class="level4" data-number="25.3.0.1">
<h4 data-number="25.3.0.1" class="anchored" data-anchor-id="real-example"><span class="header-section-number">25.3.0.1</span> Real Example</h4>
<p>If we analyzed:</p>
<ul>
<li>Europeans</li>
<li>Africans</li>
<li>East Asians</li>
</ul>
<p>PC1 and PC2 often separate groups almost perfectly.</p>
<p>The resulting plot contains three distinct clusters.</p>
</section>
<section id="quantifying-variance-explained" class="level3" data-number="25.3.1">
<h3 data-number="25.3.1" class="anchored" data-anchor-id="quantifying-variance-explained"><span class="header-section-number">25.3.1</span> Quantifying Variance Explained</h3>
<p>Create a scree plot.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb64" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb64-1">eig <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scan</span>(</span>
<span id="cb64-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_pca.eigenval"</span></span>
<span id="cb64-3">)</span>
<span id="cb64-4"></span>
<span id="cb64-5">var_exp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> eig<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>(eig)</span>
<span id="cb64-6"></span>
<span id="cb64-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb64-8">  var_exp,</span>
<span id="cb64-9">  <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;">"b"</span>,</span>
<span id="cb64-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>,</span>
<span id="cb64-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Principal Component"</span>,</span>
<span id="cb64-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Variance Explained"</span>,</span>
<span id="cb64-13">  <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;">"Scree Plot"</span></span>
<span id="cb64-14">)</span></code></pre></div></div>
</section>
<section id="interpretation-1" class="level3" data-number="25.3.2">
<h3 data-number="25.3.2" class="anchored" data-anchor-id="interpretation-1"><span class="header-section-number">25.3.2</span> Interpretation</h3>
<p>Usually:</p>
<ul>
<li>PC1 explains most variance</li>
<li>PC2 explains less</li>
<li>later PCs explain progressively less</li>
</ul>
<p>A sharp drop indicates the important ancestry dimensions.</p>
</section>
<section id="visualizing-multiple-pcs" class="level3" data-number="25.3.3">
<h3 data-number="25.3.3" class="anchored" data-anchor-id="visualizing-multiple-pcs"><span class="header-section-number">25.3.3</span> Visualizing Multiple PCs</h3>
<p>PC1 vs PC3:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb65" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb65-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb65-2">  pcs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PC1,</span>
<span id="cb65-3">  pcs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PC3,</span>
<span id="cb65-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb65-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkgreen"</span>,</span>
<span id="cb65-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC1"</span>,</span>
<span id="cb65-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC3"</span></span>
<span id="cb65-8">)</span></code></pre></div></div>
<p>PC2 vs PC3:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb66" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb66-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb66-2">  pcs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PC2,</span>
<span id="cb66-3">  pcs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PC3,</span>
<span id="cb66-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb66-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"firebrick"</span>,</span>
<span id="cb66-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC2"</span>,</span>
<span id="cb66-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC3"</span></span>
<span id="cb66-8">)</span></code></pre></div></div>
<p>Sometimes structure only appears in later PCs.</p>
</section>
<section id="why-pcs-become-covariates" class="level3" data-number="25.3.4">
<h3 data-number="25.3.4" class="anchored" data-anchor-id="why-pcs-become-covariates"><span class="header-section-number">25.3.4</span> Why PCs Become Covariates</h3>
<p>Suppose:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY%0A"></p>
<p>is phenotype.</p>
<p>Instead of fitting:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY%20=%20SNP%0A"></p>
<p>we fit:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY%20=%0ASNP%20+%0AAge%20+%0ASex%20+%0APC1%20+%0APC2%20+%0A...%0A+%0APC10%0A"></p>
<p>The PCs absorb ancestry effects.</p>
<p>This reduces false associations.</p>
</section>
<section id="how-many-pcs-should-be-used" class="level3" data-number="25.3.5">
<h3 data-number="25.3.5" class="anchored" data-anchor-id="how-many-pcs-should-be-used"><span class="header-section-number">25.3.5</span> How Many PCs Should Be Used?</h3>
<p>Common choices:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Dataset</th>
<th>Typical PCs</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Small GWAS</td>
<td>5–10</td>
</tr>
<tr class="even">
<td>UK Biobank</td>
<td>10–20</td>
</tr>
<tr class="odd">
<td>Highly diverse cohort</td>
<td>20–40</td>
</tr>
</tbody>
</table>
<p>There is no universal answer.</p>
<p>Researchers often inspect scree plots and genomic inflation.</p>
</section>
</section>
</section>
<section id="pca-and-relatedness" class="level1" data-number="26">
<h1 data-number="26"><span class="header-section-number">26</span> PCA and Relatedness</h1>
<p>Close relatives can distort PCA.</p>
<p>For example:</p>
<ul>
<li>siblings</li>
<li>parent-child pairs</li>
<li>cousins</li>
</ul>
<p>may create artificial clusters.</p>
<p>Best practice:</p>
<ol type="1">
<li>Identify unrelated individuals.</li>
<li>Compute PCs on unrelateds.</li>
<li>Project PCs onto relatives.</li>
</ol>
<p>Tools commonly used:</p>
<ul>
<li>PLINK2</li>
<li>flashPCA</li>
<li>EIGENSOFT</li>
</ul>
<p>For this practical we compute PCs directly because the number of relatives is small.</p>
</section>
<section id="repeat-pca-for-study-2" class="level1" data-number="27">
<h1 data-number="27"><span class="header-section-number">27</span> Repeat PCA for Study 2</h1>
<p>Perform the same steps.</p>
<p>LD pruning:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb67" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb67-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb67-2">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--indep-pairwise</span> 50 5 0.2 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb67-3">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_prune</span></code></pre></div></div>
<p>Compute PCs:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb68" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb68-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study2_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb68-2">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--extract</span> study2_prune.prune.in <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb68-3">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pca</span> 10 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb68-4">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study2_pca</span></code></pre></div></div>
<p>Plot:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb69" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb69-1">pcs2 <span class="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.table</span>(</span>
<span id="cb69-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study2_pca.eigenvec"</span>,</span>
<span id="cb69-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb69-4">)</span>
<span id="cb69-5"></span>
<span id="cb69-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(pcs2) <span class="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>
<span id="cb69-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FID"</span>,</span>
<span id="cb69-8">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"IID"</span>,</span>
<span id="cb69-9">  <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;">"PC"</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;">10</span>)</span>
<span id="cb69-10">)</span>
<span id="cb69-11"></span>
<span id="cb69-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb69-13">  pcs2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PC1,</span>
<span id="cb69-14">  pcs2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PC2,</span>
<span id="cb69-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb69-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkorange"</span>,</span>
<span id="cb69-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC1"</span>,</span>
<span id="cb69-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC2"</span>,</span>
<span id="cb69-19">  <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;">"Study 2: PC1 vs PC2"</span></span>
<span id="cb69-20">)</span></code></pre></div></div>
</section>
<section id="summary" class="level1" data-number="28">
<h1 data-number="28"><span class="header-section-number">28</span> Summary</h1>
<p>In this section we learned:</p>
<ol type="1">
<li>Population stratification creates false positive GWAS hits.</li>
<li>PCA identifies ancestry differences.</li>
<li>LD pruning is required before PCA.</li>
<li>Principal components summarize genetic variation.</li>
<li>PC1 and PC2 often represent ancestry.</li>
<li>PCs are added as covariates in GWAS.</li>
<li>PCA substantially reduces confounding.</li>
</ol>
<p>At this point we have:</p>
<ul>
<li>QC’d genotype data</li>
<li>ancestry estimates</li>
<li>principal components</li>
</ul>
<p>Next we will build a Genetic Relationship Matrix (GRM) and run a mixed-model GWAS using GCTA fastGWA.</p>
</section>
<section id="part-3-genetic-relationship-matrices-grms-and-mixed-model-gwas-with-gcta-fastgwa" class="level1" data-number="29">
<h1 data-number="29"><span class="header-section-number">29</span> Part 3: Genetic Relationship Matrices (GRMs) and Mixed-Model GWAS with GCTA fastGWA</h1>
</section>
<section id="why-ordinary-gwas-can-fail" class="level1" data-number="30">
<h1 data-number="30"><span class="header-section-number">30</span> Why Ordinary GWAS Can Fail</h1>
<p>Suppose we perform a simple GWAS.</p>
<p>For each SNP we fit:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY%20=%20%5Cbeta_0%20+%20%5Cbeta_1%20SNP%20+%20%5Cepsilon%0A"></p>
<p>where:</p>
<ul>
<li>(Y) is the phenotype</li>
<li>SNP is genotype dosage (0,1,2)</li>
<li>(_1) is the SNP effect</li>
</ul>
<p>This works well if:</p>
<ul>
<li>individuals are unrelated</li>
<li>there is no population structure</li>
</ul>
<p>Unfortunately, real cohorts violate both assumptions.</p>
<p>Examples:</p>
<ul>
<li>siblings</li>
<li>cousins</li>
<li>parent-offspring pairs</li>
<li>population substructure</li>
</ul>
<p>These create correlation among observations.</p>
<p>Ordinary regression assumes observations are independent.</p>
<p>Violation of this assumption leads to:</p>
<ul>
<li>inflated test statistics</li>
<li>false positives</li>
<li>incorrect p-values</li>
</ul>
</section>
<section id="relatedness-creates-correlated-phenotypes" class="level1" data-number="31">
<h1 data-number="31"><span class="header-section-number">31</span> Relatedness Creates Correlated Phenotypes</h1>
<p>Imagine two siblings.</p>
<p>They share approximately:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A50%5C%25%0A"></p>
<p>of their genome.</p>
<p>If a trait has a genetic component, siblings tend to have similar phenotypes.</p>
<p>Their observations are therefore not independent.</p>
<p>A standard GWAS treats them as independent.</p>
<p>This underestimates uncertainty and inflates significance.</p>
</section>
<section id="the-solution-mixed-models" class="level1" data-number="32">
<h1 data-number="32"><span class="header-section-number">32</span> The Solution: Mixed Models</h1>
<p>Instead of fitting:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY%20=%20X%5Cbeta%20+%20%5Cepsilon%0A"></p>
<p>we fit:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AY%20=%20X%5Cbeta%20+%20g%20+%20%5Cepsilon%0A"></p>
<p>where:</p>
<ul>
<li>(X) = fixed effects</li>
<li>(g) = polygenic random effect</li>
<li>() = residual noise</li>
</ul>
<p>The random effect captures genetic similarity among individuals.</p>
</section>
<section id="what-is-a-genetic-relationship-matrix" class="level1" data-number="33">
<h1 data-number="33"><span class="header-section-number">33</span> What is a Genetic Relationship Matrix?</h1>
<p>A Genetic Relationship Matrix (GRM) measures genetic similarity between all pairs of individuals.</p>
<p>Suppose we have:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%0A"></p>
<p>individuals.</p>
<p>The GRM is an:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%20%5Ctimes%20N%0A"></p>
<p>matrix.</p>
<p>Example:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bbmatrix%7D%0A1.0%20&amp;%200.50%20&amp;%200.02%5C%5C%0A0.50%20&amp;%201.0%20&amp;%200.01%5C%5C%0A0.02%20&amp;%200.01%20&amp;%201.0%0A%5Cend%7Bbmatrix%7D%0A"></p>
<p>Interpretation:</p>
<ul>
<li>Individual 1 and 2 are siblings</li>
<li>Individual 3 is unrelated</li>
</ul>
</section>
<section id="relationship-values" class="level1" data-number="34">
<h1 data-number="34"><span class="header-section-number">34</span> Relationship Values</h1>
<p>Typical GRM values:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Relationship</th>
<th>Expected GRM</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Same person</td>
<td>1.0</td>
</tr>
<tr class="even">
<td>Parent-child</td>
<td>0.5</td>
</tr>
<tr class="odd">
<td>Full siblings</td>
<td>0.5</td>
</tr>
<tr class="even">
<td>Half siblings</td>
<td>0.25</td>
</tr>
<tr class="odd">
<td>Grandparent-grandchild</td>
<td>0.25</td>
</tr>
<tr class="even">
<td>First cousins</td>
<td>0.125</td>
</tr>
<tr class="odd">
<td>Unrelated</td>
<td>~0</td>
</tr>
</tbody>
</table>
<section id="how-the-grm-is-computed" class="level3" data-number="34.0.1">
<h3 data-number="34.0.1" class="anchored" data-anchor-id="how-the-grm-is-computed"><span class="header-section-number">34.0.1</span> How the GRM is Computed</h3>
<p>Suppose:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ax_%7Bij%7D%0A"></p>
<p>is genotype dosage for SNP (j) in individual (i).</p>
<p>Genotypes:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Genotype</th>
<th>Dosage</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>AA</td>
<td>0</td>
</tr>
<tr class="even">
<td>Aa</td>
<td>1</td>
</tr>
<tr class="odd">
<td>aa</td>
<td>2</td>
</tr>
</tbody>
</table>
<p>The GRM entry between individuals (i) and (k) is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AG_%7Bik%7D%0A=%0A%5Cfrac%7B1%7D%7BM%7D%0A%5Csum_%7Bj=1%7D%5E%7BM%7D%0A%5Cfrac%7B%0A(x_%7Bij%7D-2p_j)%0A(x_%7Bkj%7D-2p_j)%0A%7D%0A%7B2p_j(1-p_j)%7D%0A"></p>
<p>where:</p>
<ul>
<li>(M) = number of SNPs</li>
<li>(p_j) = allele frequency</li>
</ul>
<p>This standardizes each SNP before averaging.</p>
</section>
</section>
<section id="visualizing-a-grm" class="level1" data-number="35">
<h1 data-number="35"><span class="header-section-number">35</span> Visualizing a GRM</h1>
<p>Suppose:</p>
<pre class="text"><code>Individuals:
A
B
C
D</code></pre>
<p>A GRM heatmap might look like:</p>
<pre class="text"><code>      A    B    C    D

A   1.0 0.5 0.0 0.0
B   0.5 1.0 0.0 0.0
C   0.0 0.0 1.0 0.2
D   0.0 0.0 0.2 1.0</code></pre>
<p>A and B are siblings.</p>
<p>C and D are distant relatives.</p>
</section>
<section id="why-not-use-the-full-grm-directly" class="level1" data-number="36">
<h1 data-number="36"><span class="header-section-number">36</span> Why Not Use the Full GRM Directly?</h1>
<p>Suppose:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%20=%20500,000%0A"></p>
<p>The GRM contains:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A500000%5E2%0A=%0A250,000,000,000%0A"></p>
<p>entries.</p>
<p>This becomes enormous.</p>
<p>Computational cost grows rapidly.</p>
</section>
<section id="sparse-grms" class="level1" data-number="37">
<h1 data-number="37"><span class="header-section-number">37</span> Sparse GRMs</h1>
<p>fastGWA solves this problem.</p>
<p>Instead of storing every relationship:</p>
<pre class="text"><code>0.001
0.002
0.003</code></pre>
<p>it stores only meaningful relationships.</p>
<p>Example threshold:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A0.05%0A"></p>
<p>Any relationship below:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A0.05%0A"></p>
<p>is replaced by zero.</p>
</section>
<section id="full-vs-sparse-grm" class="level1" data-number="38">
<h1 data-number="38"><span class="header-section-number">38</span> Full vs Sparse GRM</h1>
<p>Full GRM:</p>
<pre class="text"><code>Everyone related to everyone.</code></pre>
<p>Sparse GRM:</p>
<pre class="text"><code>Only close relatives retained.</code></pre>
<p>Advantages:</p>
<ul>
<li>smaller memory footprint</li>
<li>faster computation</li>
<li>scalable to biobank-sized datasets</li>
</ul>
</section>
<section id="why-pcs-are-still-necessary" class="level1" data-number="39">
<h1 data-number="39"><span class="header-section-number">39</span> Why PCs Are Still Necessary</h1>
<p>This is one of the most important concepts in the workshop.</p>
<p>A sparse GRM captures:</p>
<ul>
<li>siblings</li>
<li>cousins</li>
<li>close relatives</li>
</ul>
<p>It does NOT capture:</p>
<ul>
<li>ancestry</li>
<li>population structure</li>
</ul>
<p>because distant relationships are set to zero.</p>
<p>Therefore:</p>
<pre class="text"><code>Sparse GRM
≠
Population Stratification Correction</code></pre>
<p>PCs are still required.</p>
</section>
<section id="what-corrects-what" class="level1" data-number="40">
<h1 data-number="40"><span class="header-section-number">40</span> What Corrects What?</h1>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Component</th>
<th>Corrects</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>PCs</td>
<td>Population stratification</td>
</tr>
<tr class="even">
<td>Sparse GRM</td>
<td>Relatedness</td>
</tr>
<tr class="odd">
<td>Mixed model</td>
<td>Polygenic background</td>
</tr>
</tbody>
</table>
<p>All are needed.</p>
</section>
<section id="step-3.1-build-the-full-grm" class="level1" data-number="41">
<h1 data-number="41"><span class="header-section-number">41</span> Step 3.1 Build the Full GRM</h1>
<p>Using GCTA:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb76" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb76-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gcta64</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb76-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb76-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-grm</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb76-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_grm <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb76-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--thread-num</span> 4</span></code></pre></div></div>
<p>Output:</p>
<pre class="text"><code>study1_grm.grm.bin
study1_grm.grm.id
study1_grm.grm.N.bin</code></pre>
</section>
<section id="what-these-files-mean" class="level1" data-number="42">
<h1 data-number="42"><span class="header-section-number">42</span> What These Files Mean</h1>
<table class="caption-top table">
<thead>
<tr class="header">
<th>File</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>.grm.bin</td>
<td>GRM values</td>
</tr>
<tr class="even">
<td>.grm.id</td>
<td>Individual IDs</td>
</tr>
<tr class="odd">
<td>.grm.N.bin</td>
<td>Number of SNPs used</td>
</tr>
</tbody>
</table>
</section>
<section id="step-3.2-create-sparse-grm" class="level1" data-number="43">
<h1 data-number="43"><span class="header-section-number">43</span> Step 3.2 Create Sparse GRM</h1>
<p>Convert the full GRM:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb78" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb78-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gcta64</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb78-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--grm</span> study1_grm <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb78-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bK-sparse</span> 0.05 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb78-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_sp_grm</span></code></pre></div></div>
<p>Threshold:</p>
<pre class="text"><code>0.05</code></pre>
<p>Relationships below 0.05 become zero.</p>
</section>
<section id="why-0.05" class="level1" data-number="44">
<h1 data-number="44"><span class="header-section-number">44</span> Why 0.05?</h1>
<p>Approximately:</p>
<pre class="text"><code>Closer than third cousins</code></pre>
<p>Recommended by GCTA developers.</p>
<p>Balances:</p>
<ul>
<li>accuracy</li>
<li>speed</li>
</ul>
</section>
<section id="preparing-covariates" class="level1" data-number="45">
<h1 data-number="45"><span class="header-section-number">45</span> Preparing Covariates</h1>
<p>GCTA requires:</p>
<pre class="text"><code>No header
FID IID covariates</code></pre>
</section>
<section id="covariates-without-pcs" class="level1" data-number="46">
<h1 data-number="46"><span class="header-section-number">46</span> Covariates Without PCs</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb82" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb82-1">cov <span class="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.table</span>(</span>
<span id="cb82-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_covariates.txt"</span>,</span>
<span id="cb82-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb82-4">)</span>
<span id="cb82-5"></span>
<span id="cb82-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write.table</span>(</span>
<span id="cb82-7">  cov[,<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb82-8">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FID"</span>,</span>
<span id="cb82-9">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"IID"</span>,</span>
<span id="cb82-10">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>,</span>
<span id="cb82-11">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"age"</span></span>
<span id="cb82-12">  )],</span>
<span id="cb82-13">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_covar_noPCs.txt"</span>,</span>
<span id="cb82-14">  <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;">FALSE</span>,</span>
<span id="cb82-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col.names=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb82-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quote=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb82-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep=</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;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb82-18">)</span></code></pre></div></div>
</section>
<section id="covariates-with-pcs" class="level1" data-number="47">
<h1 data-number="47"><span class="header-section-number">47</span> Covariates With PCs</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb83" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb83-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write.table</span>(</span>
<span id="cb83-2">  cov[,<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb83-3">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FID"</span>,</span>
<span id="cb83-4">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"IID"</span>,</span>
<span id="cb83-5">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>,</span>
<span id="cb83-6">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"age"</span>,</span>
<span id="cb83-7">      <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;">"PC"</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;">10</span>)</span>
<span id="cb83-8">  )],</span>
<span id="cb83-9">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_covar_withPCs.txt"</span>,</span>
<span id="cb83-10">  <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;">FALSE</span>,</span>
<span id="cb83-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col.names=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb83-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quote=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb83-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep=</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;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb83-14">)</span></code></pre></div></div>
</section>
<section id="prepare-phenotype-file" class="level1" data-number="48">
<h1 data-number="48"><span class="header-section-number">48</span> Prepare Phenotype File</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb84" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb84-1">pheno <span class="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.table</span>(</span>
<span id="cb84-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_pheno.txt"</span>,</span>
<span id="cb84-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb84-4">)</span>
<span id="cb84-5"></span>
<span id="cb84-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write.table</span>(</span>
<span id="cb84-7">  pheno,</span>
<span id="cb84-8">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_pheno_gcta.txt"</span>,</span>
<span id="cb84-9">  <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;">FALSE</span>,</span>
<span id="cb84-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col.names=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb84-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quote=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb84-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep=</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;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb84-13">)</span></code></pre></div></div>
</section>
<section id="gwas-without-pc-adjustment" class="level1" data-number="49">
<h1 data-number="49"><span class="header-section-number">49</span> GWAS Without PC Adjustment</h1>
<p>First run the model WITHOUT PCs.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb85" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb85-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gcta64</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb85-2"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--fastGWA-mlm</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb85-3"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb85-4"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--grm-sparse</span> study1_sp_grm <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb85-5"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pheno</span> study1_pheno_gcta.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb85-6"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--qcovar</span> study1_covar_noPCs.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb85-7"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_noPCs <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb85-8"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--thread-num</span> 4</span></code></pre></div></div>
</section>
<section id="why-do-this" class="level1" data-number="50">
<h1 data-number="50"><span class="header-section-number">50</span> Why Do This?</h1>
<p>To see the effect of population stratification.</p>
<p>The sparse GRM corrects:</p>
<pre class="text"><code>relatedness</code></pre>
<p>but not:</p>
<pre class="text"><code>ancestry</code></pre>
</section>
<section id="gwas-with-pc-adjustment" class="level1" data-number="51">
<h1 data-number="51"><span class="header-section-number">51</span> GWAS With PC Adjustment</h1>
<p>Now run the proper model.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb88" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb88-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gcta64</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb88-2"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--fastGWA-mlm</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb88-3"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb88-4"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--grm-sparse</span> study1_sp_grm <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb88-5"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--pheno</span> study1_pheno_gcta.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb88-6"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--qcovar</span> study1_covar_withPCs.txt <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb88-7"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_withPCs <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb88-8"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--thread-num</span> 4</span></code></pre></div></div>
<p>Now we correct:</p>
<ul>
<li>relatedness</li>
<li>ancestry</li>
</ul>
<p>simultaneously.</p>
</section>
<section id="understanding-fastgwa-output" class="level1" data-number="52">
<h1 data-number="52"><span class="header-section-number">52</span> Understanding fastGWA Output</h1>
<p>Inspect:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb89" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb89-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_withPCs.fastGWA</span></code></pre></div></div>
<p>Important columns:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Column</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>CHR</td>
<td>Chromosome</td>
</tr>
<tr class="even">
<td>SNP</td>
<td>SNP ID</td>
</tr>
<tr class="odd">
<td>POS</td>
<td>Base-pair position</td>
</tr>
<tr class="even">
<td>A1</td>
<td>Effect allele</td>
</tr>
<tr class="odd">
<td>A2</td>
<td>Other allele</td>
</tr>
<tr class="even">
<td>AF1</td>
<td>Effect allele frequency</td>
</tr>
<tr class="odd">
<td>BETA</td>
<td>Effect size</td>
</tr>
<tr class="even">
<td>SE</td>
<td>Standard error</td>
</tr>
<tr class="odd">
<td>P</td>
<td>P-value</td>
</tr>
</tbody>
</table>
</section>
<section id="interpreting-beta" class="level1" data-number="53">
<h1 data-number="53"><span class="header-section-number">53</span> Interpreting Beta</h1>
<p>Example:</p>
<pre class="text"><code>BETA = 0.25</code></pre>
<p>means:</p>
<p>Each additional copy of the effect allele increases the phenotype by 0.25 units.</p>
</section>
<section id="interpreting-standard-error" class="level1" data-number="54">
<h1 data-number="54"><span class="header-section-number">54</span> Interpreting Standard Error</h1>
<p>Smaller:</p>
<pre class="text"><code>SE</code></pre>
<p>means more precise estimates.</p>
<p>Larger sample sizes generally reduce SE.</p>
</section>
<section id="interpreting-p-values" class="level1" data-number="55">
<h1 data-number="55"><span class="header-section-number">55</span> Interpreting P-values</h1>
<p>The null hypothesis:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbeta%20=%200%0A"></p>
<p>Small p-values suggest association.</p>
<p>Typical threshold:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A5%5Ctimes10%5E%7B-8%7D%0A"></p>
</section>
<section id="why-genome-wide-significance-is-so-stringent" class="level1" data-number="56">
<h1 data-number="56"><span class="header-section-number">56</span> Why Genome-Wide Significance Is So Stringent</h1>
<p>We test:</p>
<pre class="text"><code>Hundreds of thousands
to
Millions
of SNPs</code></pre>
<p>Multiple testing becomes severe.</p>
<p>Therefore:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A5%5Ctimes10%5E%7B-8%7D%0A"></p>
<p>is the accepted threshold.</p>
</section>
<section id="repeat-for-study-2" class="level1" data-number="57">
<h1 data-number="57"><span class="header-section-number">57</span> Repeat for Study 2</h1>
<p>Repeat:</p>
<ol type="1">
<li>Build full GRM</li>
<li>Build sparse GRM</li>
<li>Create covariates</li>
<li>Prepare phenotype file</li>
<li>Run fastGWA without PCs</li>
<li>Run fastGWA with PCs</li>
</ol>
<p>Output:</p>
<pre class="text"><code>study2_noPCs.fastGWA

study2_withPCs.fastGWA</code></pre>
</section>
<section id="summary-1" class="level1" data-number="58">
<h1 data-number="58"><span class="header-section-number">58</span> Summary</h1>
<p>In this section we learned:</p>
<ol type="1">
<li>Why ordinary regression fails in related samples.</li>
<li>What a GRM measures.</li>
<li>How a GRM is computed.</li>
<li>Why sparse GRMs are used.</li>
<li>Why PCs are still required.</li>
<li>How fastGWA works.</li>
<li>How to run mixed-model GWAS.</li>
<li>How to interpret fastGWA output.</li>
</ol>
<p>At this point we have completed the association analysis itself.</p>
<p>Next we will visualize the results using:</p>
<ul>
<li>QQ plots</li>
<li>Manhattan plots</li>
<li>Genomic inflation factor λ</li>
</ul>
<p>to determine whether our GWAS results are trustworthy.</p>
</section>
<section id="part-4-visualizing-gwas-results-with-qq-plots-and-manhattan-plots" class="level1" data-number="59">
<h1 data-number="59"><span class="header-section-number">59</span> Part 4: Visualizing GWAS Results with QQ Plots and Manhattan Plots</h1>
</section>
<section id="why-visualization-matters" class="level1" data-number="60">
<h1 data-number="60"><span class="header-section-number">60</span> Why Visualization Matters</h1>
<p>Running a GWAS produces a table containing thousands or millions of p-values.</p>
<p>A table is difficult to interpret.</p>
<p>Visualization helps answer important questions:</p>
<ol type="1">
<li>Is there population stratification?</li>
<li>Is there inflation of test statistics?</li>
<li>Are there genuine associations?</li>
<li>How many loci reach genome-wide significance?</li>
<li>Are significant SNPs clustered in genomic regions?</li>
</ol>
<p>Two plots dominate GWAS visualization:</p>
<ul>
<li>QQ plots</li>
<li>Manhattan plots</li>
</ul>
<p>These plots appear in almost every GWAS publication.</p>
</section>
<section id="loading-gwas-results" class="level1" data-number="61">
<h1 data-number="61"><span class="header-section-number">61</span> Loading GWAS Results</h1>
<p>Switch to R.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb94" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb94-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(qqman)</span>
<span id="cb94-2"></span>
<span id="cb94-3">res_noPCs <span class="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.table</span>(</span>
<span id="cb94-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_noPCs.fastGWA"</span>,</span>
<span id="cb94-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb94-6">)</span>
<span id="cb94-7"></span>
<span id="cb94-8">res_withPCs <span class="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.table</span>(</span>
<span id="cb94-9">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_withPCs.fastGWA"</span>,</span>
<span id="cb94-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb94-11">)</span></code></pre></div></div>
</section>
<section id="preparing-data-for-qqman" class="level1" data-number="62">
<h1 data-number="62"><span class="header-section-number">62</span> Preparing Data for qqman</h1>
<p>The qqman package expects:</p>
<pre class="text"><code>SNP
CHR
BP
P</code></pre>
<p>columns.</p>
<p>Create helper function:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb96" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb96-1">prep <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>(df){</span>
<span id="cb96-2"></span>
<span id="cb96-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb96-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">SNP =</span> df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>SNP,</span>
<span id="cb96-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">CHR =</span> df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>CHR,</span>
<span id="cb96-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">BP =</span> df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>POS,</span>
<span id="cb96-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">P =</span> df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P</span>
<span id="cb96-8">  )</span>
<span id="cb96-9"></span>
<span id="cb96-10">}</span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb97" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb97-1">qq_noPCs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">prep</span>(res_noPCs)</span>
<span id="cb97-2"></span>
<span id="cb97-3">qq_withPCs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">prep</span>(res_withPCs)</span></code></pre></div></div>
</section>
<section id="understanding-the-null-hypothesis" class="level1" data-number="63">
<h1 data-number="63"><span class="header-section-number">63</span> Understanding the Null Hypothesis</h1>
<p>For every SNP we test:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH_0:%5Cbeta=0%0A"></p>
<p>Under the null hypothesis:</p>
<ul>
<li>SNP has no effect</li>
<li>p-values follow a Uniform(0,1) distribution</li>
</ul>
<p>Therefore:</p>
<pre class="text"><code>Most p-values should be large.
Few p-values should be small.</code></pre>
<p>If the null is true everywhere:</p>
<pre class="text"><code>Observed p-values
≈
Expected p-values</code></pre>
</section>
<section id="what-is-a-qq-plot" class="level1" data-number="64">
<h1 data-number="64"><span class="header-section-number">64</span> What is a QQ Plot?</h1>
<p>QQ stands for:</p>
<pre class="text"><code>Quantile-Quantile</code></pre>
<p>A QQ plot compares:</p>
<ul>
<li>observed p-values</li>
<li>expected p-values under the null</li>
</ul>
<p>Instead of plotting p-values directly, we use:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A-%5Clog_%7B10%7D(p)%0A"></p>
<p>because small p-values become easier to see.</p>
</section>
<section id="expected-pattern-under-the-null" class="level1" data-number="65">
<h1 data-number="65"><span class="header-section-number">65</span> Expected Pattern Under the Null</h1>
<p>If all SNPs are null:</p>
<pre class="text"><code>Observed ≈ Expected</code></pre>
<p>The points fall on the diagonal.</p>
<p>Visually:</p>
<pre class="text"><code>|
|      /
|     /
|    /
|   /
|__/________</code></pre>
</section>
<section id="creating-qq-plots" class="level1" data-number="66">
<h1 data-number="66"><span class="header-section-number">66</span> Creating QQ Plots</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb103" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb103-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">par</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mfrow=</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>
<span id="cb103-2"></span>
<span id="cb103-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qq</span>(</span>
<span id="cb103-4">  qq_noPCs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P,</span>
<span id="cb103-5">  <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;">"QQ Plot: No PC Adjustment"</span></span>
<span id="cb103-6">)</span>
<span id="cb103-7"></span>
<span id="cb103-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qq</span>(</span>
<span id="cb103-9">  qq_withPCs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P,</span>
<span id="cb103-10">  <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;">"QQ Plot: With PC Adjustment"</span></span>
<span id="cb103-11">)</span></code></pre></div></div>
</section>
<section id="interpreting-qq-plots" class="level1" data-number="67">
<h1 data-number="67"><span class="header-section-number">67</span> Interpreting QQ Plots</h1>
<p>There are three common patterns.</p>
</section>
<section id="pattern-1-perfect-null" class="level1" data-number="68">
<h1 data-number="68"><span class="header-section-number">68</span> Pattern 1: Perfect Null</h1>
<pre class="text"><code>All points on diagonal</code></pre>
<p>Interpretation:</p>
<ul>
<li>no inflation</li>
<li>no true signal</li>
</ul>
</section>
<section id="pattern-2-global-inflation" class="level1" data-number="69">
<h1 data-number="69"><span class="header-section-number">69</span> Pattern 2: Global Inflation</h1>
<pre class="text"><code>Points rise above diagonal everywhere</code></pre>
<p>Interpretation:</p>
<p>Possible causes:</p>
<ul>
<li>population stratification</li>
<li>batch effects</li>
<li>cryptic relatedness</li>
<li>poor QC</li>
</ul>
<p>This is usually bad.</p>
</section>
<section id="pattern-3-tail-deviation" class="level1" data-number="70">
<h1 data-number="70"><span class="header-section-number">70</span> Pattern 3: Tail Deviation</h1>
<pre class="text"><code>Most points on diagonal
Only tail rises</code></pre>
<p>Interpretation:</p>
<ul>
<li>true genetic associations</li>
<li>well-controlled GWAS</li>
</ul>
<p>This is the desired pattern.</p>
<div id="5e52bada" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:18:35.753756Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:18:35.753449Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:18:36.166294Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:18:36.165253Z&quot;}}" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb107" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb107-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Illustrative simulation -- NOT real fastGWA output.</span></span>
<span id="cb107-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Reproduces the three QQ plot patterns described above: a perfect null,</span></span>
<span id="cb107-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># global inflation, and a well-controlled GWAS with true signal in the tail.</span></span>
<span id="cb107-4"></span>
<span id="cb107-5"><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="cb107-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb107-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> scipy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> stats</span>
<span id="cb107-8"></span>
<span id="cb107-9">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;">42</span>)</span>
<span id="cb107-10">n_snp <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;">20000</span></span>
<span id="cb107-11"></span>
<span id="cb107-12"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> qq_coords(pvals):</span>
<span id="cb107-13">    obs <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>np.log10(np.sort(pvals))</span>
<span id="cb107-14">    exp <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>np.log10(np.linspace(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(pvals), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(pvals)))</span>
<span id="cb107-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> exp, obs</span>
<span id="cb107-16"></span>
<span id="cb107-17">p_null <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.uniform(<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>, n_snp)</span>
<span id="cb107-18"></span>
<span id="cb107-19">lambda_inflate <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.8</span></span>
<span id="cb107-20">chisq_true <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats.chi2.rvs(df<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>, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_snp, 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;">42</span>)</span>
<span id="cb107-21">p_inflated <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="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> stats.chi2.cdf(chisq_true <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lambda_inflate, df<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="cb107-22"></span>
<span id="cb107-23">p_signal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.uniform(<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>, n_snp)</span>
<span id="cb107-24">n_hits <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;">25</span></span>
<span id="cb107-25">p_signal[:n_hits] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.uniform(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-12</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-8</span>, n_hits)</span>
<span id="cb107-26"></span>
<span id="cb107-27">fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<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>, figsize<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;">13</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.3</span>))</span>
<span id="cb107-28">titles <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;">"Perfect Null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Global Inflation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"True Signal in Tail"</span>]</span>
<span id="cb107-29">datasets <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [p_null, p_inflated, p_signal]</span>
<span id="cb107-30"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> ax, title, pvals <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;">zip</span>(axes, titles, datasets):</span>
<span id="cb107-31">    exp, obs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> qq_coords(pvals)</span>
<span id="cb107-32">    lim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(exp.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(), obs.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()) <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.05</span></span>
<span id="cb107-33">    ax.plot([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, lim], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, lim], color<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;">"#ddd8cd"</span>, linewidth<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.2</span>, linestyle<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;">"--"</span>)</span>
<span id="cb107-34">    ax.scatter(exp, obs, s<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;">4</span>, color<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;">"#2f6f6b"</span>, 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.5</span>)</span>
<span id="cb107-35">    ax.set_title(title, fontsize<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;">12</span>)</span>
<span id="cb107-36">    ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expected $-log_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{10}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">(p)$"</span>)</span>
<span id="cb107-37">    ax.set_xlim(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, lim)</span>
<span id="cb107-38">    ax.set_ylim(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, lim)</span>
<span id="cb107-39">axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Observed $-log_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{10}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">(p)$"</span>)</span>
<span id="cb107-40">fig.suptitle(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QQ Plot Patterns (Simulated)"</span>, fontweight<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;">"bold"</span>, y<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.02</span>)</span>
<span id="cb107-41">plt.tight_layout()</span>
<span id="cb107-42">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/GWAS/GWAS_files/figure-html/cell-4-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="why-pc-adjustment-matters" class="level1" data-number="71">
<h1 data-number="71"><span class="header-section-number">71</span> Why PC Adjustment Matters</h1>
<p>Compare:</p>
<pre class="text"><code>No PCs</code></pre>
<p>versus</p>
<pre class="text"><code>With PCs</code></pre>
<p>If PCs successfully correct stratification:</p>
<ul>
<li>inflation decreases</li>
<li>QQ plot approaches diagonal</li>
</ul>
<p>This demonstrates why PCA was necessary.</p>
</section>
<section id="the-genomic-inflation-factor-λ" class="level1" data-number="72">
<h1 data-number="72"><span class="header-section-number">72</span> The Genomic Inflation Factor (λ)</h1>
<p>A QQ plot is visual.</p>
<p>Lambda provides a numerical summary.</p>
<p>Definition:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Clambda%0A=%0A%5Cfrac%7B%0A%5Ctext%7Bmedian%20observed%20%7D%20%5Cchi%5E2%0A%7D%7B%0A%5Ctext%7Bmedian%20expected%20%7D%20%5Cchi%5E2%0A%7D%0A"></p>
<p>For 1 degree of freedom:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cchi%5E2_%7B0.5%7D%0A=%0A0.455%0A"></p>
</section>
<section id="computing-lambda" class="level1" data-number="73">
<h1 data-number="73"><span class="header-section-number">73</span> Computing Lambda</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb110" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb110-1">lambda <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>
<span id="cb110-2"></span>
<span id="cb110-3">  chisq <span class="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>
<span id="cb110-4">    <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,</span>
<span id="cb110-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb110-6">  )</span>
<span id="cb110-7"></span>
<span id="cb110-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(chisq) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span></span>
<span id="cb110-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qchisq</span>(</span>
<span id="cb110-10">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>,</span>
<span id="cb110-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb110-12">  )</span>
<span id="cb110-13"></span>
<span id="cb110-14">}</span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb111" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb111-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(</span>
<span id="cb111-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lambda (No PCs):"</span>,</span>
<span id="cb111-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lambda</span>(qq_noPCs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P),</span>
<span id="cb111-4">  <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></span>
<span id="cb111-5">)</span>
<span id="cb111-6"></span>
<span id="cb111-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(</span>
<span id="cb111-8">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lambda (With PCs):"</span>,</span>
<span id="cb111-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lambda</span>(qq_withPCs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P),</span>
<span id="cb111-10">  <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></span>
<span id="cb111-11">)</span></code></pre></div></div>
</section>
<section id="interpreting-lambda" class="level1" data-number="74">
<h1 data-number="74"><span class="header-section-number">74</span> Interpreting Lambda</h1>
<table class="caption-top table">
<thead>
<tr class="header">
<th>λ</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1.00</td>
<td>Ideal</td>
</tr>
<tr class="even">
<td>1.02</td>
<td>Very good</td>
</tr>
<tr class="odd">
<td>1.05</td>
<td>Usually acceptable</td>
</tr>
<tr class="even">
<td>&gt;1.10</td>
<td>Investigate inflation</td>
</tr>
<tr class="odd">
<td>&gt;1.20</td>
<td>Likely problematic</td>
</tr>
</tbody>
</table>
</section>
<section id="important-caveat" class="level1" data-number="75">
<h1 data-number="75"><span class="header-section-number">75</span> Important Caveat</h1>
<p>Many beginners think:</p>
<pre class="text"><code>λ &gt; 1
means
bad GWAS</code></pre>
<p>This is not always true.</p>
<p>Large studies often have:</p>
<ul>
<li>thousands of real associations</li>
<li>highly polygenic traits</li>
</ul>
<p>True signal can also increase λ.</p>
<p>Therefore:</p>
<p>QQ plots should always be interpreted together with λ.</p>
</section>
<section id="manhattan-plots" class="level1" data-number="76">
<h1 data-number="76"><span class="header-section-number">76</span> Manhattan Plots</h1>
<p>QQ plots summarize the whole GWAS.</p>
<p>Manhattan plots show where signals occur.</p>
<p>Each SNP is plotted according to:</p>
<ul>
<li>genomic position</li>
<li>significance</li>
</ul>
</section>
<section id="why-the-name-manhattan" class="level1" data-number="77">
<h1 data-number="77"><span class="header-section-number">77</span> Why the Name “Manhattan”?</h1>
<p>Significant loci appear as towers.</p>
<p>These resemble skyscrapers in Manhattan.</p>
<div id="3fb8807e" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:18:36.168162Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:18:36.168007Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:18:36.406991Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:18:36.406059Z&quot;}}" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb113" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb113-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Illustrative simulation -- NOT real fastGWA output.</span></span>
<span id="cb113-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulates genome-wide p-values across 10 chromosomes with one true locus,</span></span>
<span id="cb113-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># to show what a real association "tower" looks like against the null background.</span></span>
<span id="cb113-4"></span>
<span id="cb113-5"><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="cb113-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb113-7"></span>
<span id="cb113-8">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;">7</span>)</span>
<span id="cb113-9">n_chr, snps_per_chr <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>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1500</span></span>
<span id="cb113-10">true_chr, true_pos_center <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;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">700</span></span>
<span id="cb113-11"></span>
<span id="cb113-12">chrom, pos, pval <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [], [], []</span>
<span id="cb113-13">cum_offset <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="cb113-14">chrom_offsets <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb113-15"></span>
<span id="cb113-16"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> c <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>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, n_chr <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="cb113-17">    p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.sort(rng.integers(<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;">250_000_000</span>, snps_per_chr))</span>
<span id="cb113-18">    pv <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.uniform(<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>, snps_per_chr)</span>
<span id="cb113-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> true_chr:</span>
<span id="cb113-20">        window <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, true_pos_center <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;">15</span>), true_pos_center <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;">15</span>)</span>
<span id="cb113-21">        pv[window] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.uniform(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-10</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-8</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(pv[window]))</span>
<span id="cb113-22">    chrom.extend([c] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> snps_per_chr)</span>
<span id="cb113-23">    pos.extend(p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> cum_offset)</span>
<span id="cb113-24">    pval.extend(pv)</span>
<span id="cb113-25">    chrom_offsets.append(cum_offset <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> p.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>() <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>
<span id="cb113-26">    cum_offset <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> p.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>() <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;">20_000_000</span></span>
<span id="cb113-27"></span>
<span id="cb113-28">chrom, pos, pval <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array(chrom), np.array(pos), np.array(pval)</span>
<span id="cb113-29">neglog_p <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>np.log10(pval)</span>
<span id="cb113-30"></span>
<span id="cb113-31">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<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;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb113-32">colors_cycle <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;">"#2f6f6b"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#4a5a68"</span>]</span>
<span id="cb113-33"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> c <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>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, n_chr <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="cb113-34">    mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chrom <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> c</span>
<span id="cb113-35">    ax.scatter(pos[mask], neglog_p[mask], s<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;">5</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>colors_cycle[c <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>], 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.7</span>)</span>
<span id="cb113-36">ax.axhline(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>np.log10(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-8</span>), color<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;">"#b9812c"</span>, linestyle<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;">"--"</span>, linewidth<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.3</span>, label<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;">"Genome-wide (5e-8)"</span>)</span>
<span id="cb113-37">ax.axhline(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>np.log10(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-5</span>), color<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;">"#4a5a68"</span>, linestyle<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;">":"</span>, linewidth<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.1</span>, label<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;">"Suggestive (1e-5)"</span>)</span>
<span id="cb113-38">ax.set_xticks(chrom_offsets)</span>
<span id="cb113-39">ax.set_xticklabels(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, n_chr <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="cb113-40">ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chromosome"</span>)</span>
<span id="cb113-41">ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$-log_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{10}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">(p)$"</span>)</span>
<span id="cb113-42">ax.set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Manhattan Plot (Simulated Data with One True Locus on Chr </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>true_chr<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>
<span id="cb113-43">ax.legend(frameon<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>, fontsize<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;">9</span>)</span>
<span id="cb113-44">plt.tight_layout()</span>
<span id="cb113-45">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/GWAS/GWAS_files/figure-html/cell-5-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="constructing-manhattan-plots" class="level1" data-number="78">
<h1 data-number="78"><span class="header-section-number">78</span> Constructing Manhattan Plots</h1>
<p>The x-axis:</p>
<pre class="text"><code>Chromosomal position</code></pre>
<p>The y-axis:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A-%5Clog_%7B10%7D(p)%0A"></p>
<p>Small p-values become tall peaks.</p>
</section>
<section id="plotting-results" class="level1" data-number="79">
<h1 data-number="79"><span class="header-section-number">79</span> Plotting Results</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb115" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb115-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">par</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mfrow=</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;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb115-2"></span>
<span id="cb115-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">manhattan</span>(</span>
<span id="cb115-4">  qq_noPCs,</span>
<span id="cb115-5">  <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;">"No PC Adjustment"</span>,</span>
<span id="cb115-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">suggestiveline=</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;">log10</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-5</span>),</span>
<span id="cb115-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">genomewideline=</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;">log10</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-8</span>)</span>
<span id="cb115-8">)</span>
<span id="cb115-9"></span>
<span id="cb115-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">manhattan</span>(</span>
<span id="cb115-11">  qq_withPCs,</span>
<span id="cb115-12">  <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;">"With PC Adjustment"</span>,</span>
<span id="cb115-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">suggestiveline=</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;">log10</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-5</span>),</span>
<span id="cb115-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">genomewideline=</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;">log10</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-8</span>)</span>
<span id="cb115-15">)</span></code></pre></div></div>
</section>
<section id="understanding-the-threshold-lines" class="level1" data-number="80">
<h1 data-number="80"><span class="header-section-number">80</span> Understanding the Threshold Lines</h1>
<p>The blue line:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A10%5E%7B-5%7D%0A"></p>
<p>is the suggestive threshold.</p>
<p>The red line:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A5%5Ctimes10%5E%7B-8%7D%0A"></p>
<p>is the genome-wide significance threshold.</p>
</section>
<section id="why-510⁸" class="level1" data-number="81">
<h1 data-number="81"><span class="header-section-number">81</span> Why 5×10⁻⁸?</h1>
<p>Historically:</p>
<p>Approximately one million independent tests occur in a European GWAS.</p>
<p>Using Bonferroni correction:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A0.05%0A/%0A10%5E6%0A=%0A5%5Ctimes10%5E%7B-8%7D%0A"></p>
<p>This became the standard threshold.</p>
</section>
<section id="what-does-a-true-signal-look-like" class="level1" data-number="82">
<h1 data-number="82"><span class="header-section-number">82</span> What Does a True Signal Look Like?</h1>
<p>A true causal locus rarely appears as a single SNP.</p>
<p>Instead:</p>
<pre class="text"><code>Many nearby SNPs become significant</code></pre>
<p>because of linkage disequilibrium.</p>
<p>Result:</p>
<pre class="text"><code>Tower</code></pre>
<p>rather than:</p>
<pre class="text"><code>Single isolated point</code></pre>
</section>
<section id="example-1" class="level1" data-number="83">
<h1 data-number="83"><span class="header-section-number">83</span> Example</h1>
<p>Good signal:</p>
<pre class="text"><code>      *
     ***
    *****
   *******</code></pre>
<p>Suspicious signal:</p>
<pre class="text"><code>      *</code></pre>
<p>A single isolated SNP often indicates:</p>
<ul>
<li>genotyping error</li>
<li>poor imputation</li>
<li>technical artifact</li>
</ul>
</section>
<section id="comparing-no-pc-and-pc-adjusted-results" class="level1" data-number="84">
<h1 data-number="84"><span class="header-section-number">84</span> Comparing No-PC and PC-Adjusted Results</h1>
<p>Ask:</p>
<ol type="1">
<li>Do significant loci remain?</li>
<li>Do some peaks disappear?</li>
<li>Does inflation decrease?</li>
</ol>
<p>Possible outcome:</p>
<pre class="text"><code>No PCs:
Many peaks

With PCs:
Fewer peaks</code></pre>
<p>Interpretation:</p>
<p>Many initial hits were likely due to stratification.</p>
</section>
<section id="identifying-top-hits" class="level1" data-number="85">
<h1 data-number="85"><span class="header-section-number">85</span> Identifying Top Hits</h1>
<p>Find the most significant SNPs.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb122" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb122-1">top_hits <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> res_withPCs[</span>
<span id="cb122-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">order</span>(res_withPCs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P),</span>
<span id="cb122-3">]</span>
<span id="cb122-4"></span>
<span id="cb122-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(</span>
<span id="cb122-6">  top_hits[</span>
<span id="cb122-7">    ,</span>
<span id="cb122-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb122-9">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CHR"</span>,</span>
<span id="cb122-10">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SNP"</span>,</span>
<span id="cb122-11">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"POS"</span>,</span>
<span id="cb122-12">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BETA"</span>,</span>
<span id="cb122-13">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SE"</span>,</span>
<span id="cb122-14">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"P"</span></span>
<span id="cb122-15">    )</span>
<span id="cb122-16">  ]</span>
<span id="cb122-17">)</span></code></pre></div></div>
</section>
<section id="volcano-plot-optional" class="level1" data-number="86">
<h1 data-number="86"><span class="header-section-number">86</span> Volcano Plot (Optional)</h1>
<p>Although uncommon in GWAS, a volcano plot can visualize:</p>
<ul>
<li>effect size</li>
<li>significance</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb123" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb123-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb123-2">  res_withPCs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>BETA,</span>
<span id="cb123-3">  <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;">log10</span>(res_withPCs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P),</span>
<span id="cb123-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pch=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb123-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rgb</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;">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.3</span>),</span>
<span id="cb123-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Beta"</span>,</span>
<span id="cb123-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-log10(P)"</span>,</span>
<span id="cb123-8">  <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;">"Volcano Plot"</span></span>
<span id="cb123-9">)</span></code></pre></div></div>
</section>
<section id="why-manhattan-plots-are-more-popular" class="level1" data-number="87">
<h1 data-number="87"><span class="header-section-number">87</span> Why Manhattan Plots Are More Popular</h1>
<p>Volcano plots ignore:</p>
<pre class="text"><code>Genomic position</code></pre>
<p>Manhattan plots preserve:</p>
<pre class="text"><code>Chromosome
Position
LD structure</code></pre>
<p>making them more informative.</p>
</section>
<section id="common-gwas-visualization-mistakes" class="level1" data-number="88">
<h1 data-number="88"><span class="header-section-number">88</span> Common GWAS Visualization Mistakes</h1>
<section id="mistake-1" class="level2" data-number="88.1">
<h2 data-number="88.1" class="anchored" data-anchor-id="mistake-1"><span class="header-section-number">88.1</span> Mistake 1</h2>
<p>Reporting Manhattan plots without QQ plots.</p>
<p>You cannot assess inflation.</p>
</section>
<section id="mistake-2" class="level2" data-number="88.2">
<h2 data-number="88.2" class="anchored" data-anchor-id="mistake-2"><span class="header-section-number">88.2</span> Mistake 2</h2>
<p>Reporting λ without QQ plots.</p>
<p>You lose context.</p>
</section>
<section id="mistake-3" class="level2" data-number="88.3">
<h2 data-number="88.3" class="anchored" data-anchor-id="mistake-3"><span class="header-section-number">88.3</span> Mistake 3</h2>
<p>Ignoring isolated significant SNPs.</p>
<p>True loci usually form peaks.</p>
</section>
<section id="mistake-4" class="level2" data-number="88.4">
<h2 data-number="88.4" class="anchored" data-anchor-id="mistake-4"><span class="header-section-number">88.4</span> Mistake 4</h2>
<p>Comparing Manhattan plots from different studies without checking sample size.</p>
<p>Larger studies naturally produce stronger signals.</p>
</section>
</section>
<section id="study-2-visualization" class="level1" data-number="89">
<h1 data-number="89"><span class="header-section-number">89</span> Study 2 Visualization</h1>
<p>Repeat:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb126" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb126-1">res2_noPCs <span class="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.table</span>(</span>
<span id="cb126-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study2_noPCs.fastGWA"</span>,</span>
<span id="cb126-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb126-4">)</span>
<span id="cb126-5"></span>
<span id="cb126-6">res2_withPCs <span class="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.table</span>(</span>
<span id="cb126-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study2_withPCs.fastGWA"</span>,</span>
<span id="cb126-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb126-9">)</span></code></pre></div></div>
<p>Create:</p>
<ul>
<li>QQ plots</li>
<li>λ values</li>
<li>Manhattan plots</li>
</ul>
<p>Compare:</p>
<ul>
<li>Study 1</li>
<li>Study 2</li>
</ul>
<p>before meta-analysis.</p>
</section>
<section id="summary-2" class="level1" data-number="90">
<h1 data-number="90"><span class="header-section-number">90</span> Summary</h1>
<p>In this section we learned:</p>
<ol type="1">
<li>Why GWAS visualization is essential.</li>
<li>How QQ plots detect inflation.</li>
<li>How λ is calculated.</li>
<li>Why λ &gt; 1 is not always problematic.</li>
<li>How Manhattan plots display genome-wide associations.</li>
<li>Why true loci form towers.</li>
<li>How PC adjustment affects GWAS results.</li>
</ol>
<p>At this point we have:</p>
<ul>
<li>QC’d data</li>
<li>principal components</li>
<li>mixed-model GWAS results</li>
<li>visualized associations</li>
</ul>
<p>Next we will combine Study 1 and Study 2 using METAL and perform GWAS meta-analysis.</p>
<section id="part-5-gwas-meta-analysis-using-metal" class="level3" data-number="90.0.1">
<h3 data-number="90.0.1" class="anchored" data-anchor-id="part-5-gwas-meta-analysis-using-metal"><span class="header-section-number">90.0.1</span> Part 5: GWAS Meta-Analysis Using METAL</h3>
</section>
<section id="why-meta-analysis" class="level3" data-number="90.0.2">
<h3 data-number="90.0.2" class="anchored" data-anchor-id="why-meta-analysis"><span class="header-section-number">90.0.2</span> Why Meta-Analysis?</h3>
<p>Suppose we run GWAS in:</p>
<ul>
<li>Study 1 (N = 2,000)</li>
<li>Study 2 (N = 2,500)</li>
</ul>
<p>Each study may lack sufficient power to detect small genetic effects.</p>
<p>Many complex traits are highly polygenic.</p>
<p>Most SNP effects are extremely small.</p>
<p>For example:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbeta%20=%200.02%0A"></p>
<p>may require tens of thousands of samples for reliable detection.</p>
<p>Instead of analyzing studies separately, we can combine evidence across studies.</p>
<p>This process is called:</p>
<section id="meta-analysis" class="level4" data-number="90.0.2.1">
<h4 data-number="90.0.2.1" class="anchored" data-anchor-id="meta-analysis"><span class="header-section-number">90.0.2.1</span> Meta-Analysis</h4>
</section>
</section>
<section id="advantages-of-meta-analysis" class="level3" data-number="90.0.3">
<h3 data-number="90.0.3" class="anchored" data-anchor-id="advantages-of-meta-analysis"><span class="header-section-number">90.0.3</span> Advantages of Meta-Analysis</h3>
<p>Meta-analysis:</p>
<ul>
<li>increases sample size</li>
<li>increases statistical power</li>
<li>improves effect-size estimation</li>
<li>identifies consistent signals</li>
<li>avoids sharing individual-level genotype data</li>
</ul>
<p>This last point is particularly important.</p>
<p>Many large consortia share only:</p>
<ul>
<li>effect sizes</li>
<li>standard errors</li>
<li>p-values</li>
</ul>
<p>rather than raw genotype data.</p>
<section id="historical-perspective" class="level4" data-number="90.0.3.1">
<h4 data-number="90.0.3.1" class="anchored" data-anchor-id="historical-perspective"><span class="header-section-number">90.0.3.1</span> Historical Perspective</h4>
<p>Many famous GWAS discoveries were found through meta-analysis.</p>
<p>Examples include:</p>
<ul>
<li>GIANT Consortium (height, BMI)</li>
<li>Psychiatric Genomics Consortium (PGC)</li>
<li>CARDIoGRAM</li>
<li>DIAGRAM</li>
<li>Alzheimer’s Disease Genetics Consortium</li>
</ul>
<p>Modern GWAS often combine:</p>
<pre class="text"><code>10
20
50
100+
cohorts</code></pre>
<section id="fixed-effect-meta-analysis" class="level5" data-number="90.0.3.1.1">
<h5 data-number="90.0.3.1.1" class="anchored" data-anchor-id="fixed-effect-meta-analysis"><span class="header-section-number">90.0.3.1.1</span> Fixed-Effect Meta-Analysis</h5>
<p>The simplest model assumes:</p>
<p>Every study estimates the same underlying genetic effect.</p>
<p>Suppose:</p>
<p>Study 1 estimates:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%7B%5Cbeta%7D_1%0A"></p>
<p>with standard error:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0ASE_1%0A"></p>
<p>Study 2 estimates:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%7B%5Cbeta%7D_2%0A"></p>
<p>with standard error:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0ASE_2%0A"></p>
</section>
</section>
<section id="inverse-variance-weighting" class="level4" data-number="90.0.3.2">
<h4 data-number="90.0.3.2" class="anchored" data-anchor-id="inverse-variance-weighting"><span class="header-section-number">90.0.3.2</span> Inverse Variance Weighting</h4>
<p>The combined effect is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%7B%5Cbeta%7D_%7Bmeta%7D%0A=%0A%5Cfrac%7B%0Aw_1%5Chat%7B%5Cbeta%7D_1%0A+%0Aw_2%5Chat%7B%5Cbeta%7D_2%0A%7D%0A%7B%0Aw_1+w_2%0A%7D%0A"></p>
<p>where:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Aw_i%0A=%0A%5Cfrac%7B1%7D%7BSE_i%5E2%7D%0A"></p>
<p>Studies with smaller standard errors receive larger weights.</p>
</section>
<section id="why-larger-studies-get-more-weight" class="level4" data-number="90.0.3.3">
<h4 data-number="90.0.3.3" class="anchored" data-anchor-id="why-larger-studies-get-more-weight"><span class="header-section-number">90.0.3.3</span> Why Larger Studies Get More Weight</h4>
<p>Large studies generally have:</p>
<ul>
<li>smaller standard errors</li>
<li>more precise estimates</li>
</ul>
<p>Therefore:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0ASE%20%5Cdownarrow%0A%5CRightarrow%0AWeight%20%5Cuparrow%0A"></p>
<p>This is exactly what we want.</p>
<p>More reliable studies contribute more strongly.</p>
</section>
</section>
<section id="what-does-metal-do" class="level3" data-number="90.0.4">
<h3 data-number="90.0.4" class="anchored" data-anchor-id="what-does-metal-do"><span class="header-section-number">90.0.4</span> What Does METAL Do?</h3>
<p>METAL is one of the most widely used GWAS meta-analysis programs.</p>
<p>Input:</p>
<pre class="text"><code>Summary statistics</code></pre>
<p>Output:</p>
<pre class="text"><code>Combined summary statistics</code></pre>
<p>METAL does not require:</p>
<ul>
<li>genotype data</li>
<li>phenotype data</li>
<li>individual-level covariates</li>
</ul>
<p>Only GWAS summary statistics are needed.</p>
<section id="preparing-gwas-results" class="level4" data-number="90.0.4.1">
<h4 data-number="90.0.4.1" class="anchored" data-anchor-id="preparing-gwas-results"><span class="header-section-number">90.0.4.1</span> Preparing GWAS Results</h4>
<p>We previously generated:</p>
<pre class="text"><code>study1_withPCs.fastGWA

study2_withPCs.fastGWA</code></pre>
<p>These files contain:</p>
<ul>
<li>SNP</li>
<li>chromosome</li>
<li>position</li>
<li>beta</li>
<li>standard error</li>
<li>p-value</li>
</ul>
</section>
<section id="inspecting-results" class="level4" data-number="90.0.4.2">
<h4 data-number="90.0.4.2" class="anchored" data-anchor-id="inspecting-results"><span class="header-section-number">90.0.4.2</span> Inspecting Results</h4>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb131" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb131-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study1_withPCs.fastGWA</span>
<span id="cb131-2"></span>
<span id="cb131-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> study2_withPCs.fastGWA</span></code></pre></div></div>
</section>
<section id="required-columns" class="level4" data-number="90.0.4.3">
<h4 data-number="90.0.4.3" class="anchored" data-anchor-id="required-columns"><span class="header-section-number">90.0.4.3</span> Required Columns</h4>
<p>METAL typically requires:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Column</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>SNP</td>
<td>Variant identifier</td>
</tr>
<tr class="even">
<td>A1</td>
<td>Effect allele</td>
</tr>
<tr class="odd">
<td>A2</td>
<td>Other allele</td>
</tr>
<tr class="even">
<td>BETA</td>
<td>Effect size</td>
</tr>
<tr class="odd">
<td>SE</td>
<td>Standard error</td>
</tr>
<tr class="even">
<td>P</td>
<td>P-value</td>
</tr>
</tbody>
</table>
</section>
<section id="harmonization" class="level4" data-number="90.0.4.4">
<h4 data-number="90.0.4.4" class="anchored" data-anchor-id="harmonization"><span class="header-section-number">90.0.4.4</span> Harmonization</h4>
<p>Before meta-analysis:</p>
<p>effect alleles must match.</p>
<p>For example:</p>
<p>Study 1:</p>
<pre class="text"><code>A = effect allele
G = reference allele</code></pre>
<p>Study 2:</p>
<pre class="text"><code>G = effect allele
A = reference allele</code></pre>
<p>If not corrected:</p>
<p>effect estimates will point in opposite directions.</p>
<p>This can completely invalidate results.</p>
</section>
<section id="example-2" class="level4" data-number="90.0.4.5">
<h4 data-number="90.0.4.5" class="anchored" data-anchor-id="example-2"><span class="header-section-number">90.0.4.5</span> Example</h4>
<p>Study 1:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbeta%20=%20+0.15%0A"></p>
<p>Study 2:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbeta%20=%20-0.15%0A"></p>
<p>The apparent disagreement may be entirely due to allele coding.</p>
<p>Always harmonize alleles.</p>
</section>
<section id="creating-a-metal-script" class="level4" data-number="90.0.4.6">
<h4 data-number="90.0.4.6" class="anchored" data-anchor-id="creating-a-metal-script"><span class="header-section-number">90.0.4.6</span> Creating a METAL Script</h4>
<p>Create:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb134" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb134-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">metal_script.txt</span></span></code></pre></div></div>
</section>
</section>
</section>
<section id="contents" class="level1" data-number="91">
<h1 data-number="91"><span class="header-section-number">91</span> Contents</h1>
<pre class="text"><code>SCHEME STDERR

MARKER SNP

ALLELE A1 A2

EFFECT BETA

STDERR SE

PVAL P

PROCESS study1_withPCs.fastGWA

PROCESS study2_withPCs.fastGWA

OUTFILE meta_results .

ANALYZE

QUIT</code></pre>
</section>
<section id="understanding-the-commands" class="level1" data-number="92">
<h1 data-number="92"><span class="header-section-number">92</span> Understanding the Commands</h1>
<section id="scheme-stderr" class="level2" data-number="92.1">
<h2 data-number="92.1" class="anchored" data-anchor-id="scheme-stderr"><span class="header-section-number">92.1</span> SCHEME STDERR</h2>
<p>Use inverse-variance weighting.</p>
<p>Weights:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Aw_i=%5Cfrac%7B1%7D%7BSE_i%5E2%7D%0A"></p>
</section>
<section id="marker" class="level2" data-number="92.2">
<h2 data-number="92.2" class="anchored" data-anchor-id="marker"><span class="header-section-number">92.2</span> MARKER</h2>
<p>Specifies SNP identifier column.</p>
<pre class="text"><code>SNP</code></pre>
</section>
<section id="effect" class="level2" data-number="92.3">
<h2 data-number="92.3" class="anchored" data-anchor-id="effect"><span class="header-section-number">92.3</span> EFFECT</h2>
<p>Specifies effect-size column.</p>
<pre class="text"><code>BETA</code></pre>
</section>
<section id="stderr" class="level2" data-number="92.4">
<h2 data-number="92.4" class="anchored" data-anchor-id="stderr"><span class="header-section-number">92.4</span> STDERR</h2>
<p>Specifies standard error column.</p>
<pre class="text"><code>SE</code></pre>
</section>
<section id="process" class="level2" data-number="92.5">
<h2 data-number="92.5" class="anchored" data-anchor-id="process"><span class="header-section-number">92.5</span> PROCESS</h2>
<p>Loads a study.</p>
<pre class="text"><code>PROCESS study1
PROCESS study2</code></pre>
</section>
<section id="analyze" class="level2" data-number="92.6">
<h2 data-number="92.6" class="anchored" data-anchor-id="analyze"><span class="header-section-number">92.6</span> ANALYZE</h2>
<p>Runs the meta-analysis.</p>
</section>
</section>
<section id="running-metal" class="level1" data-number="93">
<h1 data-number="93"><span class="header-section-number">93</span> Running METAL</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb140" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb140-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">metal</span> metal_script.txt</span></code></pre></div></div>
<p>Output:</p>
<pre class="text"><code>meta_results1.tbl</code></pre>
</section>
<section id="inspecting-meta-analysis-results" class="level1" data-number="94">
<h1 data-number="94"><span class="header-section-number">94</span> Inspecting Meta-Analysis Results</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb142" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb142-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span> meta_results1.tbl</span></code></pre></div></div>
<p>Common columns:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Column</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>MarkerName</td>
<td>SNP ID</td>
</tr>
<tr class="even">
<td>Allele1</td>
<td>Effect allele</td>
</tr>
<tr class="odd">
<td>Allele2</td>
<td>Other allele</td>
</tr>
<tr class="even">
<td>Effect</td>
<td>Combined beta</td>
</tr>
<tr class="odd">
<td>StdErr</td>
<td>Combined SE</td>
</tr>
<tr class="even">
<td>P-value</td>
<td>Meta-analysis p-value</td>
</tr>
<tr class="odd">
<td>Direction</td>
<td>Sign of effect in each study</td>
</tr>
</tbody>
</table>
</section>
<section id="understanding-direction" class="level1" data-number="95">
<h1 data-number="95"><span class="header-section-number">95</span> Understanding Direction</h1>
<p>Example:</p>
<pre class="text"><code>++</code></pre>
<p>Both studies:</p>
<pre class="text"><code>positive effect</code></pre>
<p>Example:</p>
<pre class="text"><code>--</code></pre>
<p>Both studies:</p>
<pre class="text"><code>negative effect</code></pre>
<p>Example:</p>
<pre class="text"><code>+-</code></pre>
<p>Studies disagree.</p>
<p>This may indicate:</p>
<ul>
<li>heterogeneity</li>
<li>allele issues</li>
<li>random variation</li>
</ul>
</section>
<section id="why-meta-analysis-increases-power" class="level1" data-number="96">
<h1 data-number="96"><span class="header-section-number">96</span> Why Meta-Analysis Increases Power</h1>
<p>Suppose:</p>
<p>Study 1:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP=10%5E%7B-4%7D%0A"></p>
<p>Study 2:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP=10%5E%7B-3%7D%0A"></p>
<p>Neither reaches:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A5%5Ctimes10%5E%7B-8%7D%0A"></p>
<p>alone.</p>
<p>Combined analysis may produce:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP=10%5E%7B-9%7D%0A"></p>
<p>This is why meta-analysis dominates modern GWAS.</p>
</section>
<section id="comparing-gwas-and-meta-analysis" class="level1" data-number="97">
<h1 data-number="97"><span class="header-section-number">97</span> Comparing GWAS and Meta-Analysis</h1>
<p>Load results in R.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb148" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb148-1">study1 <span class="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.table</span>(</span>
<span id="cb148-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_withPCs.fastGWA"</span>,</span>
<span id="cb148-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb148-4">)</span>
<span id="cb148-5"></span>
<span id="cb148-6">study2 <span class="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.table</span>(</span>
<span id="cb148-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study2_withPCs.fastGWA"</span>,</span>
<span id="cb148-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb148-9">)</span>
<span id="cb148-10"></span>
<span id="cb148-11">meta <span class="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.table</span>(</span>
<span id="cb148-12">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"meta_results1.tbl"</span>,</span>
<span id="cb148-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb148-14">)</span></code></pre></div></div>
</section>
<section id="number-of-significant-hits" class="level1" data-number="98">
<h1 data-number="98"><span class="header-section-number">98</span> Number of Significant Hits</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb149" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb149-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(</span>
<span id="cb149-2">  study1<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;">5e-8</span></span>
<span id="cb149-3">)</span>
<span id="cb149-4"></span>
<span id="cb149-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(</span>
<span id="cb149-6">  study2<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;">5e-8</span></span>
<span id="cb149-7">)</span>
<span id="cb149-8"></span>
<span id="cb149-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(</span>
<span id="cb149-10">  meta<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P.value <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;">5e-8</span></span>
<span id="cb149-11">)</span></code></pre></div></div>
</section>
<section id="interpretation-2" class="level1" data-number="99">
<h1 data-number="99"><span class="header-section-number">99</span> Interpretation</h1>
<p>Typically:</p>
<pre class="text"><code>Meta-analysis
&gt;
Individual studies</code></pre>
<p>in terms of discoveries.</p>
</section>
<section id="manhattan-plot-of-meta-analysis" class="level1" data-number="100">
<h1 data-number="100"><span class="header-section-number">100</span> Manhattan Plot of Meta-Analysis</h1>
<p>Prepare data.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb151" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb151-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(qqman)</span>
<span id="cb151-2"></span>
<span id="cb151-3">meta_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;">data.frame</span>(</span>
<span id="cb151-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">SNP =</span> meta<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>MarkerName,</span>
<span id="cb151-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">CHR =</span> meta<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Chromosome,</span>
<span id="cb151-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">BP =</span> meta<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Position,</span>
<span id="cb151-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">P =</span> meta<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P.value</span>
<span id="cb151-8">)</span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb152" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb152-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">manhattan</span>(</span>
<span id="cb152-2">  meta_plot,</span>
<span id="cb152-3">  <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;">"Meta-analysis Manhattan Plot"</span>,</span>
<span id="cb152-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">suggestiveline=</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;">log10</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-5</span>),</span>
<span id="cb152-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">genomewideline=</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;">log10</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-8</span>)</span>
<span id="cb152-6">)</span></code></pre></div></div>
</section>
<section id="qq-plot-of-meta-analysis" class="level1" data-number="101">
<h1 data-number="101"><span class="header-section-number">101</span> QQ Plot of Meta-Analysis</h1>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb153" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb153-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qq</span>(</span>
<span id="cb153-2">  meta<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P.value,</span>
<span id="cb153-3">  <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;">"Meta-analysis QQ Plot"</span></span>
<span id="cb153-4">)</span></code></pre></div></div>
</section>
<section id="heterogeneity" class="level1" data-number="102">
<h1 data-number="102"><span class="header-section-number">102</span> Heterogeneity</h1>
<p>One of the most important concepts in meta-analysis is:</p>
<section id="heterogeneity-1" class="level2" data-number="102.1">
<h2 data-number="102.1" class="anchored" data-anchor-id="heterogeneity-1"><span class="header-section-number">102.1</span> Heterogeneity</h2>
<p>Suppose:</p>
<p>Study 1:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbeta%20=%200.20%0A"></p>
<p>Study 2:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbeta%20=%200.18%0A"></p>
<p>These are consistent.</p>
<p>Now suppose:</p>
<p>Study 1:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbeta%20=%200.25%0A"></p>
<p>Study 2:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbeta%20=%20-0.20%0A"></p>
<p>These are inconsistent.</p>
<p>This is heterogeneity.</p>
</section>
</section>
<section id="cochrans-q-statistic" class="level1" data-number="103">
<h1 data-number="103"><span class="header-section-number">103</span> Cochran’s Q Statistic</h1>
<p>Many meta-analysis tools evaluate:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AQ%0A=%0A%5Csum%0Aw_i%0A(%0A%5Cbeta_i-%5Cbeta_%7Bmeta%7D%0A)%5E2%0A"></p>
<p>Large Q values indicate disagreement among studies.</p>
</section>
<section id="i²-statistic" class="level1" data-number="104">
<h1 data-number="104"><span class="header-section-number">104</span> I² Statistic</h1>
<p>Another common metric:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AI%5E2%0A=%0A100%5C%25%0A%5Ctimes%0A%5Cfrac%7BQ-df%7D%7BQ%7D%0A"></p>
<p>Interpretation:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>I²</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0%</td>
<td>No heterogeneity</td>
</tr>
<tr class="even">
<td>25%</td>
<td>Low</td>
</tr>
<tr class="odd">
<td>50%</td>
<td>Moderate</td>
</tr>
<tr class="even">
<td>75%</td>
<td>High</td>
</tr>
</tbody>
</table>
</section>
<section id="why-heterogeneity-matters" class="level1" data-number="105">
<h1 data-number="105"><span class="header-section-number">105</span> Why Heterogeneity Matters</h1>
<p>Heterogeneity may arise from:</p>
<ul>
<li>ancestry differences</li>
<li>environmental differences</li>
<li>phenotype definitions</li>
<li>technical differences</li>
<li>gene-environment interaction</li>
</ul>
</section>
<section id="mystery-phenotype-investigation" class="level1" data-number="106">
<h1 data-number="106"><span class="header-section-number">106</span> Mystery Phenotype Investigation</h1>
<p>The workshop asks:</p>
<blockquote class="blockquote">
<p>Can we identify the phenotype from the strongest GWAS hit?</p>
</blockquote>
<p>Procedure:</p>
<ol type="1">
<li>Find the top SNP.</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb154" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb154-1">top_snp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> meta[</span>
<span id="cb154-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.min</span>(meta<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>P.value),</span>
<span id="cb154-3">]</span>
<span id="cb154-4"></span>
<span id="cb154-5">top_snp</span></code></pre></div></div>
<ol start="2" type="1">
<li>Record:</li>
</ol>
<pre class="text"><code>rsID</code></pre>
<ol start="3" type="1">
<li>Search:</li>
</ol>
<ul>
<li>GWAS Catalog</li>
<li>Ensembl</li>
<li>dbSNP</li>
<li>Open Targets Genetics</li>
</ul>
<ol start="4" type="1">
<li>Compare previously reported traits.</li>
</ol>
<p>This often provides clues regarding phenotype identity.</p>
</section>
<section id="example-resources" class="level1" data-number="107">
<h1 data-number="107"><span class="header-section-number">107</span> Example Resources</h1>
<p>Useful databases:</p>
<ul>
<li><a href="https://www.ebi.ac.uk/gwas/">GWAS Catalog</a></li>
<li><a href="https://www.ensembl.org/">Ensembl</a></li>
<li><a href="https://www.ncbi.nlm.nih.gov/snp/">dbSNP</a></li>
<li><a href="https://genetics.opentargets.org/">Open Targets Genetics</a></li>
</ul>
</section>
<section id="summary-3" class="level1" data-number="108">
<h1 data-number="108"><span class="header-section-number">108</span> Summary</h1>
<p>In this section we learned:</p>
<ol type="1">
<li>Why GWAS meta-analysis is necessary.</li>
<li>How inverse-variance weighting works.</li>
<li>How METAL combines studies.</li>
<li>Why allele harmonization matters.</li>
<li>How to interpret meta-analysis results.</li>
<li>How heterogeneity is assessed.</li>
<li>Why meta-analysis increases power.</li>
<li>How to identify candidate phenotypes using top SNPs.</li>
</ol>
<p>At this point we have completed:</p>
<ul>
<li>QC</li>
<li>PCA</li>
<li>GRM construction</li>
<li>fastGWA analysis</li>
<li>QQ plots</li>
<li>Manhattan plots</li>
<li>Meta-analysis</li>
</ul>
<p>The final section will focus on:</p>
<ul>
<li>inspecting relatedness directly from the GRM</li>
<li>identifying relatives</li>
<li>interpreting GRM values</li>
<li>understanding cryptic relatedness</li>
<li>best practices for large-scale GWAS.</li>
</ul>
<section id="part-6-understanding-relatedness-grms-and-best-practices-for-gwas" class="level3" data-number="108.0.1">
<h3 data-number="108.0.1" class="anchored" data-anchor-id="part-6-understanding-relatedness-grms-and-best-practices-for-gwas"><span class="header-section-number">108.0.1</span> Part 6: Understanding Relatedness, GRMs, and Best Practices for GWAS</h3>
<section id="why-relatedness-matters" class="level4" data-number="108.0.1.1">
<h4 data-number="108.0.1.1" class="anchored" data-anchor-id="why-relatedness-matters"><span class="header-section-number">108.0.1.1</span> Why Relatedness Matters</h4>
<p>One of the fundamental assumptions of classical statistical tests is:</p>
<blockquote class="blockquote">
<p>Observations are independent.</p>
</blockquote>
<p>In genetic studies this assumption is often violated.</p>
<p>Individuals may be:</p>
<ul>
<li>siblings</li>
<li>parent-child pairs</li>
<li>cousins</li>
<li>twins</li>
<li>members of the same pedigree</li>
</ul>
<p>These relationships introduce correlation.</p>
<p>If ignored, GWAS statistics become inflated.</p>
</section>
<section id="what-is-cryptic-relatedness" class="level4" data-number="108.0.1.2">
<h4 data-number="108.0.1.2" class="anchored" data-anchor-id="what-is-cryptic-relatedness"><span class="header-section-number">108.0.1.2</span> What is Cryptic Relatedness?</h4>
<p>Cryptic relatedness means:</p>
<blockquote class="blockquote">
<p>Individuals are genetically related, but the relationship is unknown or unrecorded.</p>
</blockquote>
<p>Examples:</p>
<ul>
<li>unknown cousins</li>
<li>undocumented family relationships</li>
<li>pedigree errors</li>
<li>duplicate samples</li>
</ul>
<p>Large biobanks often contain thousands of related individuals.</p>
</section>
<section id="historical-perspective-1" class="level4" data-number="108.0.1.3">
<h4 data-number="108.0.1.3" class="anchored" data-anchor-id="historical-perspective-1"><span class="header-section-number">108.0.1.3</span> Historical Perspective</h4>
<p>Early GWAS often removed relatives.</p>
<p>Modern GWAS typically retain relatives and use mixed models.</p>
<p>Why?</p>
<p>Because removing relatives wastes valuable samples.</p>
<p>Mixed models allow us to:</p>
<ul>
<li>retain individuals</li>
<li>model relatedness directly</li>
<li>increase statistical power</li>
</ul>
</section>
<section id="revisiting-the-genetic-relationship-matrix" class="level4" data-number="108.0.1.4">
<h4 data-number="108.0.1.4" class="anchored" data-anchor-id="revisiting-the-genetic-relationship-matrix"><span class="header-section-number">108.0.1.4</span> Revisiting the Genetic Relationship Matrix</h4>
<p>The GRM contains pairwise genetic similarity.</p>
<p>Suppose we have:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%0A"></p>
<p>individuals.</p>
<p>The GRM contains:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%5Ctimes%20N%0A"></p>
<p>entries.</p>
<p>Each cell represents:</p>
<pre class="text"><code>How genetically similar are two individuals?</code></pre>
</section>
<section id="grm-interpretation" class="level4" data-number="108.0.1.5">
<h4 data-number="108.0.1.5" class="anchored" data-anchor-id="grm-interpretation"><span class="header-section-number">108.0.1.5</span> GRM Interpretation</h4>
<p>Suppose:</p>
<pre class="text"><code>ID1 ID2 Relationship</code></pre>
<p>produces:</p>
<pre class="text"><code>0.50</code></pre>
<p>Interpretation:</p>
<p>Likely:</p>
<ul>
<li>parent-child</li>
<li>full siblings</li>
</ul>
<p>Suppose:</p>
<pre class="text"><code>0.25</code></pre>
<p>Interpretation:</p>
<p>Likely:</p>
<ul>
<li>half siblings</li>
<li>grandparent-grandchild</li>
<li>avuncular relationships</li>
</ul>
<p>Suppose:</p>
<pre class="text"><code>0.125</code></pre>
<p>Interpretation:</p>
<p>Likely:</p>
<ul>
<li>first cousins</li>
</ul>
<p>Suppose:</p>
<pre class="text"><code>0.00</code></pre>
<p>Interpretation:</p>
<p>Essentially unrelated.</p>
</section>
<section id="typical-relatedness-thresholds" class="level4" data-number="108.0.1.6">
<h4 data-number="108.0.1.6" class="anchored" data-anchor-id="typical-relatedness-thresholds"><span class="header-section-number">108.0.1.6</span> Typical Relatedness Thresholds</h4>
<table class="caption-top table">
<thead>
<tr class="header">
<th>GRM Value</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>&gt;0.95</td>
<td>Duplicate sample / identical twin</td>
</tr>
<tr class="even">
<td>~0.50</td>
<td>Parent-child or sibling</td>
</tr>
<tr class="odd">
<td>~0.25</td>
<td>Second-degree relative</td>
</tr>
<tr class="even">
<td>~0.125</td>
<td>First cousin</td>
</tr>
<tr class="odd">
<td>~0</td>
<td>Unrelated</td>
</tr>
</tbody>
</table>
<p>These values are approximate.</p>
<p>Real data fluctuate around expectations.</p>
</section>
<section id="reading-the-grm" class="level4" data-number="108.0.1.7">
<h4 data-number="108.0.1.7" class="anchored" data-anchor-id="reading-the-grm"><span class="header-section-number">108.0.1.7</span> Reading the GRM</h4>
<p>We previously generated:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb162" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb162-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">study1_grm</span></span></code></pre></div></div>
<p>using:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb163" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb163-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gcta64</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb163-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb163-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-grm</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb163-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_grm</span></code></pre></div></div>
<p>Convert GRM to text:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb164" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb164-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">gcta64</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb164-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--grm</span> study1_grm <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb164-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--grm-cutoff</span> 0 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb164-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-grm-gz</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb164-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_grm_text</span></code></pre></div></div>
<p>This produces:</p>
<pre class="text"><code>study1_grm_text.grm.gz</code></pre>
<p>Inspect:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb166" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb166-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zcat</span> study1_grm_text.grm.gz <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span></span></code></pre></div></div>
</section>
<section id="understanding-grm-columns" class="level4" data-number="108.0.1.8">
<h4 data-number="108.0.1.8" class="anchored" data-anchor-id="understanding-grm-columns"><span class="header-section-number">108.0.1.8</span> Understanding GRM Columns</h4>
<p>Typical output:</p>
<pre class="text"><code>ID1
ID2
N_SNP
GRM</code></pre>
<p>Meaning:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Column</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ID1</td>
<td>Individual 1</td>
</tr>
<tr class="even">
<td>ID2</td>
<td>Individual 2</td>
</tr>
<tr class="odd">
<td>N_SNP</td>
<td>Number of SNPs used</td>
</tr>
<tr class="even">
<td>GRM</td>
<td>Relatedness estimate</td>
</tr>
</tbody>
</table>
</section>
<section id="finding-close-relatives" class="level4" data-number="108.0.1.9">
<h4 data-number="108.0.1.9" class="anchored" data-anchor-id="finding-close-relatives"><span class="header-section-number">108.0.1.9</span> Finding Close Relatives</h4>
<p>Extract individuals with:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AGRM%20%3E%200.05%0A"></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb168" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb168-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zcat</span> study1_grm_text.grm.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb168-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">awk</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'$4 &gt; 0.05'</span></span></code></pre></div></div>
<p>These are genetically related pairs.</p>
</section>
<section id="counting-related-pairs" class="level4" data-number="108.0.1.10">
<h4 data-number="108.0.1.10" class="anchored" data-anchor-id="counting-related-pairs"><span class="header-section-number">108.0.1.10</span> Counting Related Pairs</h4>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb169" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb169-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zcat</span> study1_grm_text.grm.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb169-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">awk</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'$4 &gt; 0.05'</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb169-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wc</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span></span></code></pre></div></div>
<p>This gives:</p>
<pre class="text"><code>Number of related pairs</code></pre>
</section>
<section id="identifying-duplicates" class="level4" data-number="108.0.1.11">
<h4 data-number="108.0.1.11" class="anchored" data-anchor-id="identifying-duplicates"><span class="header-section-number">108.0.1.11</span> Identifying Duplicates</h4>
<p>Potential duplicates:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb171" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb171-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zcat</span> study1_grm_text.grm.gz <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb171-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">awk</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'$4 &gt; 0.95'</span></span></code></pre></div></div>
<p>Interpretation:</p>
<p>Possible:</p>
<ul>
<li>duplicated sample</li>
<li>monozygotic twins</li>
<li>sample labeling error</li>
</ul>
<p>These should be investigated.</p>
</section>
<section id="visualizing-the-grm" class="level4" data-number="108.0.1.12">
<h4 data-number="108.0.1.12" class="anchored" data-anchor-id="visualizing-the-grm"><span class="header-section-number">108.0.1.12</span> Visualizing the GRM</h4>
<p>Switch to R.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb172" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb172-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(data.table)</span>
<span id="cb172-2"></span>
<span id="cb172-3">grm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fread</span>(</span>
<span id="cb172-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"study1_grm_text.grm.gz"</span></span>
<span id="cb172-5">)</span></code></pre></div></div>
</section>
<section id="heatmap-of-relatedness" class="level4" data-number="108.0.1.13">
<h4 data-number="108.0.1.13" class="anchored" data-anchor-id="heatmap-of-relatedness"><span class="header-section-number">108.0.1.13</span> Heatmap of Relatedness</h4>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb173" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb173-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb173-2"></span>
<span id="cb173-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(</span>
<span id="cb173-4">  grm,</span>
<span id="cb173-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(</span>
<span id="cb173-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x=</span>V1,</span>
<span id="cb173-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y=</span>V2,</span>
<span id="cb173-8">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill=</span>V4</span>
<span id="cb173-9">  )</span>
<span id="cb173-10">)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb173-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_tile</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb173-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_gradient</span>(</span>
<span id="cb173-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">low=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>,</span>
<span id="cb173-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">high=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span></span>
<span id="cb173-15">)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb173-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb173-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb173-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genetic Relationship Matrix"</span></span>
<span id="cb173-19">)</span></code></pre></div></div>
</section>
<section id="interpretation-3" class="level4" data-number="108.0.1.14">
<h4 data-number="108.0.1.14" class="anchored" data-anchor-id="interpretation-3"><span class="header-section-number">108.0.1.14</span> Interpretation</h4>
<p>Bright red regions indicate:</p>
<ul>
<li>families</li>
<li>clusters of relatives</li>
</ul>
<p>White regions indicate:</p>
<ul>
<li>unrelated individuals</li>
</ul>
<div id="0f261cc7" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;execution&quot;,&quot;value&quot;:{&quot;iopub.execute_input&quot;:&quot;2026-07-30T17:18:36.409290Z&quot;,&quot;iopub.status.busy&quot;:&quot;2026-07-30T17:18:36.408595Z&quot;,&quot;iopub.status.idle&quot;:&quot;2026-07-30T17:18:36.589117Z&quot;,&quot;shell.execute_reply&quot;:&quot;2026-07-30T17:18:36.588199Z&quot;}}" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb174" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb174-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Illustrative simulation -- NOT a real GRM from GCTA.</span></span>
<span id="cb174-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulates a small GRM for 20 individuals including two sibling pairs,</span></span>
<span id="cb174-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one parent-child pair, and one first-cousin pair, to make the heatmap</span></span>
<span id="cb174-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># and "finding close relatives" discussion concrete.</span></span>
<span id="cb174-5"></span>
<span id="cb174-6"><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="cb174-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb174-8"></span>
<span id="cb174-9">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;">42</span>)</span>
<span id="cb174-10">n_ind <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;">20</span></span>
<span id="cb174-11">grm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.zeros((n_ind, n_ind))</span>
<span id="cb174-12">np.fill_diagonal(grm, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>)</span>
<span id="cb174-13">base_noise <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.normal(<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.015</span>, (n_ind, n_ind))</span>
<span id="cb174-14">grm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> (base_noise <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> base_noise.T) <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>
<span id="cb174-15">np.fill_diagonal(grm, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>)</span>
<span id="cb174-16"></span>
<span id="cb174-17">sib_pairs <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 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;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)]</span>
<span id="cb174-18"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sib_pairs:</span>
<span id="cb174-19">    grm[i, j] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> grm[j, i] <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.5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> rng.normal(<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.02</span>)</span>
<span id="cb174-20">grm[<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;">9</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> grm[<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;">8</span>] <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.5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> rng.normal(<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.02</span>)          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># parent-child</span></span>
<span id="cb174-21">grm[<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;">13</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> grm[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">13</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>] <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.125</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> rng.normal(<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.02</span>)    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># first cousins</span></span>
<span id="cb174-22"></span>
<span id="cb174-23">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<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;">6</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5.3</span>))</span>
<span id="cb174-24">im <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ax.imshow(grm, cmap<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;">"YlGnBu"</span>, vmin<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>, vmax<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="cb174-25">ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Simulated Genetic Relationship Matrix (GRM)"</span>)</span>
<span id="cb174-26">ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Individual"</span>)</span>
<span id="cb174-27">ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Individual"</span>)</span>
<span id="cb174-28">cbar <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fig.colorbar(im, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax, fraction<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.046</span>, pad<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.04</span>)</span>
<span id="cb174-29">cbar.set_label(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Relatedness"</span>)</span>
<span id="cb174-30">plt.tight_layout()</span>
<span id="cb174-31">plt.show()</span>
<span id="cb174-32"></span>
<span id="cb174-33">close_pairs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [(i, j, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(grm[i, j], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb174-34">               <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_ind) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> j <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>(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>, n_ind)</span>
<span id="cb174-35">               <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> grm[i, j] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>]</span>
<span id="cb174-36"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Detected close-relative pairs (GRM &gt; 0.05):"</span>, close_pairs)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/GWAS/GWAS_files/figure-html/cell-6-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Detected close-relative pairs (GRM &gt; 0.05): [(0, 1, np.float64(0.496)), (4, 5, np.float64(0.504)), (8, 9, np.float64(0.516)), (12, 13, np.float64(0.117))]</code></pre>
</div>
</div>
</section>
<section id="relatedness-distribution" class="level4" data-number="108.0.1.15">
<h4 data-number="108.0.1.15" class="anchored" data-anchor-id="relatedness-distribution"><span class="header-section-number">108.0.1.15</span> Relatedness Distribution</h4>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb176" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb176-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hist</span>(</span>
<span id="cb176-2">  grm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>V4,</span>
<span id="cb176-3">  <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;">100</span>,</span>
<span id="cb176-4">  <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;">"GRM Distribution"</span>,</span>
<span id="cb176-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlab=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Relatedness"</span></span>
<span id="cb176-6">)</span></code></pre></div></div>
</section>
<section id="expected-pattern" class="level4" data-number="108.0.1.16">
<h4 data-number="108.0.1.16" class="anchored" data-anchor-id="expected-pattern"><span class="header-section-number">108.0.1.16</span> Expected Pattern</h4>
<p>Most individuals should be:</p>
<pre class="text"><code>Near zero</code></pre>
<p>A small number should show:</p>
<pre class="text"><code>0.125
0.25
0.5</code></pre>
<p>indicating relatives.</p>
</section>
</section>
<section id="relationship-categories" class="level3" data-number="108.0.2">
<h3 data-number="108.0.2" class="anchored" data-anchor-id="relationship-categories"><span class="header-section-number">108.0.2</span> Relationship Categories</h3>
<p>Create categories.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb179" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb179-1">grm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>relationship <span class="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>(</span>
<span id="cb179-2">  grm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>V4,</span>
<span id="cb179-3">  <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>
<span id="cb179-4">    <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">Inf</span>,</span>
<span id="cb179-5">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>,</span>
<span id="cb179-6">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.125</span>,</span>
<span id="cb179-7">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>,</span>
<span id="cb179-8">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>,</span>
<span id="cb179-9">    <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">Inf</span></span>
<span id="cb179-10">  ),</span>
<span id="cb179-11">  <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>
<span id="cb179-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Unrelated"</span>,</span>
<span id="cb179-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Distant"</span>,</span>
<span id="cb179-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"First Cousin"</span>,</span>
<span id="cb179-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Second Degree"</span>,</span>
<span id="cb179-16">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"First Degree"</span></span>
<span id="cb179-17">  )</span>
<span id="cb179-18">)</span>
<span id="cb179-19"></span>
<span id="cb179-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(</span>
<span id="cb179-21">  grm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>relationship</span>
<span id="cb179-22">)</span></code></pre></div></div>
<section id="why-relatedness-creates-false-positives" class="level4" data-number="108.0.2.1">
<h4 data-number="108.0.2.1" class="anchored" data-anchor-id="why-relatedness-creates-false-positives"><span class="header-section-number">108.0.2.1</span> Why Relatedness Creates False Positives</h4>
<p>Suppose:</p>
<ul>
<li>siblings share 50% of genome</li>
<li>siblings share environmental exposures</li>
</ul>
<p>Phenotypes become correlated.</p>
<p>A SNP inherited within families may appear associated with the trait simply because family members resemble each other.</p>
<p>This creates inflation.</p>
</section>
</section>
<section id="classical-solution" class="level3" data-number="108.0.3">
<h3 data-number="108.0.3" class="anchored" data-anchor-id="classical-solution"><span class="header-section-number">108.0.3</span> Classical Solution</h3>
<p>Older GWAS often removed relatives.</p>
<p>Example:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb180" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb180-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">plink</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb180-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--bfile</span> study1_qc <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb180-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--rel-cutoff</span> 0.125 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb180-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--make-bed</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb180-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> study1_unrelated</span></code></pre></div></div>
<p>This removes one individual from each related pair.</p>
</section>
</section>
<section id="disadvantages" class="level1" data-number="109">
<h1 data-number="109"><span class="header-section-number">109</span> Disadvantages</h1>
<p>You lose data.</p>
<p>Example:</p>
<pre class="text"><code>20,000 samples</code></pre>
<p>may become:</p>
<pre class="text"><code>14,000 samples</code></pre>
<p>after removing relatives.</p>
<p>Power decreases.</p>
</section>
<section id="modern-solution" class="level1" data-number="110">
<h1 data-number="110"><span class="header-section-number">110</span> Modern Solution</h1>
<p>Use:</p>
<pre class="text"><code>Linear Mixed Models</code></pre>
<p>Examples:</p>
<ul>
<li>fastGWA</li>
<li>BOLT-LMM</li>
<li>SAIGE</li>
<li>REGENIE</li>
</ul>
<p>These methods:</p>
<ul>
<li>keep relatives</li>
<li>model relatedness directly</li>
</ul>
<p>This is why modern biobanks rarely remove all relatives.</p>
</section>
<section id="comparing-approaches" class="level1" data-number="111">
<h1 data-number="111"><span class="header-section-number">111</span> Comparing Approaches</h1>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Approach</th>
<th>Relatives Removed?</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>PLINK Linear Regression</td>
<td>Usually yes</td>
</tr>
<tr class="even">
<td>Mixed Models</td>
<td>No</td>
</tr>
<tr class="odd">
<td>fastGWA</td>
<td>No</td>
</tr>
<tr class="even">
<td>BOLT-LMM</td>
<td>No</td>
</tr>
<tr class="odd">
<td>REGENIE</td>
<td>No</td>
</tr>
</tbody>
</table>
</section>
<section id="why-biobanks-need-mixed-models" class="level1" data-number="112">
<h1 data-number="112"><span class="header-section-number">112</span> Why Biobanks Need Mixed Models</h1>
<p>Consider:</p>
<section id="uk-biobank" class="level3" data-number="112.0.1">
<h3 data-number="112.0.1" class="anchored" data-anchor-id="uk-biobank"><span class="header-section-number">112.0.1</span> UK Biobank</h3>
<p>Approximately:</p>
<pre class="text"><code>500,000 individuals</code></pre>
<p>Contains:</p>
<pre class="text"><code>Tens of thousands
of related individuals</code></pre>
<p>Removing all relatives would waste enormous amounts of data.</p>
<p>Mixed models solve this problem.</p>
</section>
</section>
<section id="gwas-best-practices-checklist" class="level1" data-number="113">
<h1 data-number="113"><span class="header-section-number">113</span> GWAS Best Practices Checklist</h1>
<p>Before running GWAS:</p>
<section id="sample-qc" class="level2" data-number="113.1">
<h2 data-number="113.1" class="anchored" data-anchor-id="sample-qc"><span class="header-section-number">113.1</span> Sample QC</h2>
<p>✔ Missingness</p>
<p>✔ Sex checks</p>
<p>✔ Heterozygosity</p>
<p>✔ Relatedness</p>
</section>
<section id="snp-qc" class="level2" data-number="113.2">
<h2 data-number="113.2" class="anchored" data-anchor-id="snp-qc"><span class="header-section-number">113.2</span> SNP QC</h2>
<p>✔ Missingness</p>
<p>✔ MAF filtering</p>
<p>✔ HWE filtering</p>
</section>
<section id="population-structure" class="level2" data-number="113.3">
<h2 data-number="113.3" class="anchored" data-anchor-id="population-structure"><span class="header-section-number">113.3</span> Population Structure</h2>
<p>✔ PCA</p>
<p>✔ Ancestry inspection</p>
</section>
<section id="association-analysis" class="level2" data-number="113.4">
<h2 data-number="113.4" class="anchored" data-anchor-id="association-analysis"><span class="header-section-number">113.4</span> Association Analysis</h2>
<p>✔ Mixed model</p>
<p>✔ GRM</p>
<p>✔ PCs as covariates</p>
</section>
<section id="visualization" class="level2" data-number="113.5">
<h2 data-number="113.5" class="anchored" data-anchor-id="visualization"><span class="header-section-number">113.5</span> Visualization</h2>
<p>✔ QQ plot</p>
<p>✔ Lambda</p>
<p>✔ Manhattan plot</p>
</section>
<section id="replication" class="level2" data-number="113.6">
<h2 data-number="113.6" class="anchored" data-anchor-id="replication"><span class="header-section-number">113.6</span> Replication</h2>
<p>✔ Independent cohort</p>
<p>or</p>
<p>✔ Meta-analysis</p>
<section id="common-beginner-mistakes" class="level3" data-number="113.6.1">
<h3 data-number="113.6.1" class="anchored" data-anchor-id="common-beginner-mistakes"><span class="header-section-number">113.6.1</span> Common Beginner Mistakes</h3>
</section>
<section id="mistake-1-1" class="level3" data-number="113.6.2">
<h3 data-number="113.6.2" class="anchored" data-anchor-id="mistake-1-1"><span class="header-section-number">113.6.2</span> Mistake 1</h3>
<p>Running GWAS without QC.</p>
</section>
<section id="mistake-2-1" class="level3" data-number="113.6.3">
<h3 data-number="113.6.3" class="anchored" data-anchor-id="mistake-2-1"><span class="header-section-number">113.6.3</span> Mistake 2</h3>
<p>Ignoring population structure.</p>
</section>
<section id="mistake-3-1" class="level3" data-number="113.6.4">
<h3 data-number="113.6.4" class="anchored" data-anchor-id="mistake-3-1"><span class="header-section-number">113.6.4</span> Mistake 3</h3>
<p>Ignoring relatedness.</p>
</section>
<section id="mistake-4-1" class="level3" data-number="113.6.5">
<h3 data-number="113.6.5" class="anchored" data-anchor-id="mistake-4-1"><span class="header-section-number">113.6.5</span> Mistake 4</h3>
<p>Using only p-values.</p>
<p>Effect sizes matter.</p>
</section>
<section id="mistake-5" class="level3" data-number="113.6.6">
<h3 data-number="113.6.6" class="anchored" data-anchor-id="mistake-5"><span class="header-section-number">113.6.6</span> Mistake 5</h3>
<p>Reporting isolated SNPs without checking LD.</p>
</section>
<section id="mistake-6" class="level3" data-number="113.6.7">
<h3 data-number="113.6.7" class="anchored" data-anchor-id="mistake-6"><span class="header-section-number">113.6.7</span> Mistake 6</h3>
<p>Assuming genome-wide significance proves causality.</p>
<p>GWAS identifies association, not causation.</p>
<section id="what-happens-after-gwas" class="level4" data-number="113.6.7.1">
<h4 data-number="113.6.7.1" class="anchored" data-anchor-id="what-happens-after-gwas"><span class="header-section-number">113.6.7.1</span> What Happens After GWAS?</h4>
<p>A significant GWAS hit is only the beginning.</p>
<p>Typical follow-up analyses include:</p>
<ul>
<li>Fine mapping</li>
<li>Colocalization</li>
<li>eQTL analysis</li>
<li>TWAS</li>
<li>Polygenic Risk Scores</li>
<li>Mendelian Randomization</li>
<li>Functional annotation</li>
</ul>
</section>
</section>
<section id="complete-gwas-workflow" class="level3" data-number="113.6.8">
<h3 data-number="113.6.8" class="anchored" data-anchor-id="complete-gwas-workflow"><span class="header-section-number">113.6.8</span> Complete GWAS Workflow</h3>
<p>You have now completed the entire GWAS pipeline:</p>
<pre class="text"><code>Raw Genotypes
      ↓
Quality Control
      ↓
LD Pruning
      ↓
PCA
      ↓
GRM Construction
      ↓
Mixed Model GWAS
      ↓
QQ Plot
      ↓
Manhattan Plot
      ↓
Meta-analysis
      ↓
Relatedness Inspection
      ↓
Biological Interpretation</code></pre>
<p>A GWAS is much more than running a regression for millions of SNPs.</p>
<p>Every stage exists for a reason:</p>
<ul>
<li>QC prevents technical artifacts.</li>
<li>PCA controls ancestry differences.</li>
<li>GRMs model genetic similarity.</li>
<li>Mixed models account for relatedness.</li>
<li>QQ plots diagnose inflation.</li>
<li>Manhattan plots reveal genomic loci.</li>
<li>Meta-analysis increases power.</li>
</ul>
<p>When all of these pieces work together, GWAS becomes one of the most powerful tools in modern human genetics, enabling the discovery of thousands of genetic variants associated with disease, behavior, physiology, and molecular traits.</p>


</section>
</section>
</section>

 ]]></description>
  <category>Genetics</category>
  <category>GWAS</category>
  <category>Statistical Genetics</category>
  <category>Tutorial</category>
  <guid>https://bntechie.github.io/tutorials/GWAS/GWAS.html</guid>
  <pubDate>Sun, 07 Jun 2026 21:00:00 GMT</pubDate>
  <media:content url="https://bntechie.github.io/tutorials/GWAS/images/gwas-manhattan.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Genetic Drift and Fixation: Understanding Evolution Through Randomness</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift.html</link>
  <description><![CDATA[ 




<p>When people think about evolution, they often think about <strong>natural selection</strong>.</p>
<p>Natural selection explains how advantageous genetic variants become more common because they improve survival or reproduction.</p>
<p>However, natural selection is not the only force driving evolution.</p>
<p>Even in the complete absence of selection, allele frequencies can change over time simply because populations are finite.</p>
<p>This phenomenon is called <strong>genetic drift</strong>.</p>
<p>Genetic drift is one of the most fundamental concepts in population genetics because it explains:</p>
<ul>
<li>Random changes in allele frequencies</li>
<li>Loss of genetic diversity</li>
<li>Founder effects</li>
<li>Population bottlenecks</li>
<li>Neutral evolution</li>
<li>Fixation and extinction of alleles</li>
</ul>
<p>Understanding drift is essential for modern genomics, GWAS, evolutionary biology, conservation genetics, and statistical genetics.</p>
<p>In this tutorial we will study:</p>
<ol type="1">
<li>What genetic drift is</li>
<li>Why fixation occurs</li>
<li>The Wright-Fisher model</li>
<li>Important theoretical results</li>
<li>Simulation of allele-frequency trajectories</li>
<li>Verification of classical population genetics theorems</li>
</ol>
<section id="learning-objectives" class="level3" data-number="0.1">
<h3 data-number="0.1" class="anchored" data-anchor-id="learning-objectives"><span class="header-section-number">0.1</span> Learning Objectives</h3>
<p>By the end of this tutorial you should be able to:</p>
<ul>
<li>Explain genetic drift intuitively</li>
<li>Derive the Wright-Fisher model</li>
<li>Understand fixation and extinction</li>
<li>Simulate neutral evolution</li>
<li>Interpret allele frequency trajectories</li>
<li>Understand why small populations drift faster than large populations</li>
<li>Connect drift to modern genomic studies</li>
</ul>
</section>
<section id="prerequisites" class="level3" data-number="0.2">
<h3 data-number="0.2" class="anchored" data-anchor-id="prerequisites"><span class="header-section-number">0.2</span> Prerequisites</h3>
<p>This tutorial assumes familiarity with:</p>
<ul>
<li>Basic probability</li>
<li>Binomial distributions</li>
<li>Python programming</li>
<li>Elementary genetics</li>
</ul>
<p>No prior knowledge of population genetics is required.</p>
</section>
<section id="what-is-an-allele" class="level3" data-number="0.3">
<h3 data-number="0.3" class="anchored" data-anchor-id="what-is-an-allele"><span class="header-section-number">0.3</span> What is an Allele?</h3>
<p>A gene can exist in different versions called alleles.</p>
<p>For example:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Gene</th>
<th>Alleles</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Eye color gene</td>
<td>Blue, Brown</td>
</tr>
<tr class="even">
<td>SNP rs12345</td>
<td>A, G</td>
</tr>
</tbody>
</table>
<p>Suppose a locus contains two alleles:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AA%0A"></p>
<p>and</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Aa%0A"></p>
<p>Let <img src="https://latex.codecogs.com/png.latex?p"> denote the frequency of allele A.</p>
<p>Then</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A1-p%0A"></p>
<p>is the frequency of allele a.</p>
<p>For example:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Allele</th>
<th>Frequency</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>A</td>
<td>0.7</td>
</tr>
<tr class="even">
<td>a</td>
<td>0.3</td>
</tr>
</tbody>
</table>
<p>The frequencies always sum to one.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap%20+%20(1-p)=1%0A"></p>
</section>
<section id="infinite-vs-finite-populations" class="level3" data-number="0.4">
<h3 data-number="0.4" class="anchored" data-anchor-id="infinite-vs-finite-populations"><span class="header-section-number">0.4</span> Infinite vs Finite Populations</h3>
<p>Imagine an infinitely large population.</p>
<p>If:</p>
<ul>
<li>No mutation</li>
<li>No migration</li>
<li>No selection</li>
<li>Random mating</li>
</ul>
<p>then allele frequencies remain constant forever.</p>
<p>This idealized situation is the basis of the Hardy-Weinberg equilibrium.</p>
<p>Real populations are never infinite.</p>
<p>Because populations are finite, each generation represents a random sample from the previous generation.</p>
<p>This sampling introduces randomness.</p>
<p>That randomness is genetic drift.</p>
</section>
<section id="an-intuitive-example" class="level3" data-number="0.5">
<h3 data-number="0.5" class="anchored" data-anchor-id="an-intuitive-example"><span class="header-section-number">0.5</span> An Intuitive Example</h3>
<p>Imagine a population containing:</p>
<ul>
<li>50 copies of allele A</li>
<li>50 copies of allele a</li>
</ul>
<p>The allele frequency is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=0.5%0A"></p>
<p>Now imagine forming the next generation by randomly selecting individuals.</p>
<p>By chance you may obtain:</p>
<ul>
<li>55 copies of A</li>
<li>45 copies of a</li>
</ul>
<p>Now:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=0.55%0A"></p>
<p>Nothing biological happened.</p>
<p>No selection occurred.</p>
<p>The change is purely due to chance.</p>
<p>This is genetic drift.</p>
<section id="formal-definition" class="level4" data-number="0.5.1">
<h4 data-number="0.5.1" class="anchored" data-anchor-id="formal-definition"><span class="header-section-number">0.5.1</span> Formal Definition</h4>
<p>Genetic drift is the random fluctuation of allele frequencies due to finite population sampling.</p>
<p>Unlike natural selection:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Genetic Drift</th>
<th>Natural Selection</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Random</td>
<td>Non-random</td>
</tr>
<tr class="even">
<td>Stronger in small populations</td>
<td>Can operate in any population</td>
</tr>
<tr class="odd">
<td>Does not require fitness differences</td>
<td>Requires fitness differences</td>
</tr>
<tr class="even">
<td>Can fix harmful alleles</td>
<td>Favors beneficial alleles</td>
</tr>
</tbody>
</table>
</section>
</section>
<section id="what-is-fixation" class="level3" data-number="0.6">
<h3 data-number="0.6" class="anchored" data-anchor-id="what-is-fixation"><span class="header-section-number">0.6</span> What is Fixation?</h3>
<p>An allele is fixed when its frequency becomes:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=1%0A"></p>
<p>This means every chromosome in the population carries that allele.</p>
<p>Example:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Allele</th>
<th>Frequency</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>A</td>
<td>1.0</td>
</tr>
<tr class="even">
<td>a</td>
<td>0.0</td>
</tr>
</tbody>
</table>
<p>At this point:</p>
<ul>
<li>Genetic variation disappears</li>
<li>No alternative allele remains</li>
</ul>
</section>
<section id="what-is-allele-loss" class="level3" data-number="0.7">
<h3 data-number="0.7" class="anchored" data-anchor-id="what-is-allele-loss"><span class="header-section-number">0.7</span> What is Allele Loss?</h3>
<p>The opposite situation occurs when:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=0%0A"></p>
<p>The allele disappears entirely from the population.</p>
<p>Example:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Allele</th>
<th>Frequency</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>A</td>
<td>0</td>
</tr>
<tr class="even">
<td>a</td>
<td>1</td>
</tr>
</tbody>
</table>
<p>In a drift-only model:</p>
<ul>
<li>fixation is absorbing</li>
<li>extinction is absorbing</li>
</ul>
<p>Once reached, these states remain forever.</p>
</section>
<section id="the-wright-fisher-model" class="level3" data-number="0.8">
<h3 data-number="0.8" class="anchored" data-anchor-id="the-wright-fisher-model"><span class="header-section-number">0.8</span> The Wright-Fisher Model</h3>
<p>The Wright-Fisher model is the classical mathematical model of genetic drift.</p>
<p>Assumptions:</p>
<ol type="1">
<li>Constant population size</li>
<li>Diploid individuals</li>
<li>Random mating</li>
<li>No mutation</li>
<li>No migration</li>
<li>No selection</li>
<li>Non-overlapping generations</li>
</ol>
<p>Suppose:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%0A"></p>
<p>is the number of diploid individuals.</p>
<p>There are:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A2N%0A"></p>
<p>gene copies.</p>
</section>
<section id="sampling-the-next-generation" class="level3" data-number="0.9">
<h3 data-number="0.9" class="anchored" data-anchor-id="sampling-the-next-generation"><span class="header-section-number">0.9</span> Sampling the Next Generation</h3>
<p>Suppose allele A has frequency:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap_t%0A"></p>
<p>in generation:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0At%0A"></p>
<p>The number of copies of allele A in the next generation follows:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AX_%7Bt+1%7D%0A%5Csim%0ABinomial(2N,p_t)%0A"></p>
<p>The allele frequency becomes:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap_%7Bt+1%7D%0A=%0A%5Cfrac%7BX_%7Bt+1%7D%7D%7B2N%7D%0A"></p>
<p>This simple equation forms the foundation of modern population genetics.</p>
</section>
<section id="important-theorem-1-drift-has-no-direction" class="level3" data-number="0.10">
<h3 data-number="0.10" class="anchored" data-anchor-id="important-theorem-1-drift-has-no-direction"><span class="header-section-number">0.10</span> Important Theorem 1: Drift Has No Direction</h3>
<p>For a neutral allele:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AE%5Bp_%7Bt+1%7D%5Cmid%20p_t%5D%0A=%0Ap_t%0A"></p>
<p>Interpretation:</p>
<p>On average, allele frequencies do not systematically increase or decrease.</p>
<p>Drift is unbiased.</p>
<p>However, individual populations may behave very differently.</p>
</section>
<section id="important-theorem-2-variance-of-drift" class="level3" data-number="0.11">
<h3 data-number="0.11" class="anchored" data-anchor-id="important-theorem-2-variance-of-drift"><span class="header-section-number">0.11</span> Important Theorem 2: Variance of Drift</h3>
<p>The variance is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AVar(p_%7Bt+1%7D%5Cmid%20p_t)%0A=%0A%5Cfrac%7Bp_t(1-p_t)%7D%7B2N%7D%0A"></p>
<p>This equation reveals an important biological fact:</p>
<p>Drift becomes stronger as population size decreases.</p>
</section>
<section id="why-small-populations-drift-faster" class="level3" data-number="0.12">
<h3 data-number="0.12" class="anchored" data-anchor-id="why-small-populations-drift-faster"><span class="header-section-number">0.12</span> Why Small Populations Drift Faster</h3>
<p>Suppose:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap_t=0.5%0A"></p>
<p>For</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN=20%0A"></p>
<p>the variance becomes:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B0.5%5Ctimes0.5%7D%7B40%7D%0A=%0A0.00625%0A"></p>
<p>For</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN=1000%0A"></p>
<p>the variance becomes:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B0.5%5Ctimes0.5%7D%7B2000%7D%0A=%0A0.000125%0A"></p>
<p>The smaller population experiences much larger fluctuations.</p>
</section>
<section id="important-theorem-3-fixation-probability" class="level3" data-number="0.13">
<h3 data-number="0.13" class="anchored" data-anchor-id="important-theorem-3-fixation-probability"><span class="header-section-number">0.13</span> Important Theorem 3: Fixation Probability</h3>
<p>One of the most beautiful results in population genetics states:</p>
<p>For a neutral allele:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(Fixation)=p_0%0A"></p>
<p>where</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap_0%0A"></p>
<p>is the starting frequency.</p>
<p>Examples:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Initial Frequency</th>
<th>Fixation Probability</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0.1</td>
<td>10%</td>
</tr>
<tr class="even">
<td>0.2</td>
<td>20%</td>
</tr>
<tr class="odd">
<td>0.5</td>
<td>50%</td>
</tr>
<tr class="even">
<td>0.8</td>
<td>80%</td>
</tr>
</tbody>
</table>
</section>
<section id="new-mutations" class="level3" data-number="0.14">
<h3 data-number="0.14" class="anchored" data-anchor-id="new-mutations"><span class="header-section-number">0.14</span> New Mutations</h3>
<p>A new mutation begins as a single copy.</p>
<p>In a diploid population:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap_0%0A=%0A%5Cfrac%7B1%7D%7B2N%7D%0A"></p>
<p>Therefore:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(Fixation)%0A=%0A%5Cfrac%7B1%7D%7B2N%7D%0A"></p>
<p>Example:</p>
<p>For</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN=1000%0A"></p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(Fixation)%0A=%0A0.0005%0A"></p>
<p>Only 0.05%.</p>
<p>Most neutral mutations disappear.</p>
</section>
<section id="important-theorem-4-heterozygosity-decay" class="level3" data-number="0.15">
<h3 data-number="0.15" class="anchored" data-anchor-id="important-theorem-4-heterozygosity-decay"><span class="header-section-number">0.15</span> Important Theorem 4: Heterozygosity Decay</h3>
<p>Drift reduces genetic diversity.</p>
<p>Expected heterozygosity after t generations:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH_t%0A=%0AH_0%0A%5Cleft(%0A1-%5Cfrac%7B1%7D%7B2N%7D%0A%5Cright)%5Et%0A"></p>
<p>This explains why isolated populations lose diversity over time.</p>
<div id="98f9bf54-ae8d-4483-ac09-79929e89e13e" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Setting Up Python</span></span>
<span id="cb1-2"></span>
<span id="cb1-3"></span>
<span id="cb1-4"><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="cb1-5"><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="cb1-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb1-7"></span>
<span id="cb1-8">np.random.seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span></code></pre></div></div>
</div>
</section>
<section id="simulating-the-wright-fisher-model" class="level3" data-number="0.16">
<h3 data-number="0.16" class="anchored" data-anchor-id="simulating-the-wright-fisher-model"><span class="header-section-number">0.16</span> Simulating the Wright-Fisher Model</h3>
<p>We now implement the model directly.</p>
<div id="7b6205e2-9a2b-42ba-b168-a5c65d2056d2" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> simulate_drift(</span>
<span id="cb2-2">    N<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;">100</span>,</span>
<span id="cb2-3">    p0<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.5</span>,</span>
<span id="cb2-4">    generations<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;">100</span></span>
<span id="cb2-5">):</span>
<span id="cb2-6"></span>
<span id="cb2-7">    p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> p0</span>
<span id="cb2-8"></span>
<span id="cb2-9">    trajectory <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [p]</span>
<span id="cb2-10"></span>
<span id="cb2-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <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>(generations):</span>
<span id="cb2-12"></span>
<span id="cb2-13">        count_A <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.binomial(</span>
<span id="cb2-14">            <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>N,</span>
<span id="cb2-15">            p</span>
<span id="cb2-16">        )</span>
<span id="cb2-17"></span>
<span id="cb2-18">        p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> count_A<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>N)</span>
<span id="cb2-19"></span>
<span id="cb2-20">        trajectory.append(p)</span>
<span id="cb2-21"></span>
<span id="cb2-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> p <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 class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> p <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="cb2-23"></span>
<span id="cb2-24">            trajectory.extend(</span>
<span id="cb2-25">                [p]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(generations<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(trajectory)<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="cb2-26">            )</span>
<span id="cb2-27"></span>
<span id="cb2-28">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span></span>
<span id="cb2-29"></span>
<span id="cb2-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.array(trajectory)</span>
<span id="cb2-31"></span>
<span id="cb2-32"></span>
<span id="cb2-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulating One Population</span></span>
<span id="cb2-34"></span>
<span id="cb2-35"></span>
<span id="cb2-36">trajectory <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb2-37">    N<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;">100</span>,</span>
<span id="cb2-38">    p0<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.5</span>,</span>
<span id="cb2-39">    generations<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;">200</span></span>
<span id="cb2-40">)</span>
<span id="cb2-41"></span></code></pre></div></div>
</div>
<div id="98ecd89f-3d5d-4710-aa4a-434d89d8e7d4" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"></span>
<span id="cb3-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Visualizing Drift</span></span>
<span id="cb3-3"></span>
<span id="cb3-4"></span>
<span id="cb3-5">plt.figure(figsize<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;">12</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb3-6"></span>
<span id="cb3-7">plt.plot(</span>
<span id="cb3-8">    trajectory,</span>
<span id="cb3-9">    linewidth<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>
<span id="cb3-10">)</span>
<span id="cb3-11"></span>
<span id="cb3-12">plt.axhline(</span>
<span id="cb3-13">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb3-14">    linestyle<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;">"--"</span></span>
<span id="cb3-15">)</span>
<span id="cb3-16"></span>
<span id="cb3-17">plt.axhline(</span>
<span id="cb3-18">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb3-19">    linestyle<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;">"--"</span></span>
<span id="cb3-20">)</span>
<span id="cb3-21"></span>
<span id="cb3-22">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Generation"</span>)</span>
<span id="cb3-23">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allele Frequency"</span>)</span>
<span id="cb3-24"></span>
<span id="cb3-25">plt.title(</span>
<span id="cb3-26">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Single Wright-Fisher Trajectory"</span></span>
<span id="cb3-27">)</span>
<span id="cb3-28"></span>
<span id="cb3-29">plt.ylim(</span>
<span id="cb3-30">    <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.05</span>,</span>
<span id="cb3-31">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.05</span></span>
<span id="cb3-32">)</span>
<span id="cb3-33"></span>
<span id="cb3-34">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-4-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpreting-the-plot" class="level3" data-number="0.17">
<h3 data-number="0.17" class="anchored" data-anchor-id="interpreting-the-plot"><span class="header-section-number">0.17</span> Interpreting the Plot</h3>
<p>Notice:</p>
<ul>
<li>Frequency fluctuates randomly</li>
<li>No directional trend exists</li>
<li>Changes occur despite no selection</li>
<li>Eventually fixation or extinction may occur</li>
</ul>
<p>This randomness is the hallmark of genetic drift.</p>
</section>
<section id="simulating-multiple-populations" class="level3" data-number="0.18">
<h3 data-number="0.18" class="anchored" data-anchor-id="simulating-multiple-populations"><span class="header-section-number">0.18</span> Simulating Multiple Populations</h3>
<p>The true power of drift appears when we simulate many populations with identical starting conditions.</p>
<div id="2e404d71-a89b-4b60-be4c-0bbe9ed91cea" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"></span>
<span id="cb4-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> simulate_many_populations(</span>
<span id="cb4-3">    N<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;">100</span>,</span>
<span id="cb4-4">    p0<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.5</span>,</span>
<span id="cb4-5">    generations<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;">200</span>,</span>
<span id="cb4-6">    n_replicates<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;">50</span></span>
<span id="cb4-7">):</span>
<span id="cb4-8"></span>
<span id="cb4-9">    trajectories<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb4-10"></span>
<span id="cb4-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <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_replicates):</span>
<span id="cb4-12"></span>
<span id="cb4-13">        traj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb4-14">            N,</span>
<span id="cb4-15">            p0,</span>
<span id="cb4-16">            generations</span>
<span id="cb4-17">        )</span>
<span id="cb4-18"></span>
<span id="cb4-19">        trajectories.append(traj)</span>
<span id="cb4-20"></span>
<span id="cb4-21">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.array(trajectories)</span>
<span id="cb4-22"></span>
<span id="cb4-23">trajectories <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_many_populations(</span>
<span id="cb4-24">    N<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;">100</span>,</span>
<span id="cb4-25">    p0<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.5</span>,</span>
<span id="cb4-26">    generations<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;">200</span>,</span>
<span id="cb4-27">    n_replicates<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;">50</span></span>
<span id="cb4-28">)</span>
<span id="cb4-29"></span>
<span id="cb4-30">plt.figure(figsize<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;">12</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>))</span>
<span id="cb4-31"></span>
<span id="cb4-32"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> traj <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> trajectories:</span>
<span id="cb4-33"></span>
<span id="cb4-34">    plt.plot(</span>
<span id="cb4-35">        traj,</span>
<span id="cb4-36">        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>
<span id="cb4-37">    )</span>
<span id="cb4-38"></span>
<span id="cb4-39">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Generation"</span>)</span>
<span id="cb4-40">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allele Frequency"</span>)</span>
<span id="cb4-41"></span>
<span id="cb4-42">plt.title(</span>
<span id="cb4-43">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"50 Independent Populations Starting at p=0.5"</span></span>
<span id="cb4-44">)</span>
<span id="cb4-45"></span>
<span id="cb4-46">plt.ylim(</span>
<span id="cb4-47">    <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.05</span>,</span>
<span id="cb4-48">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.05</span></span>
<span id="cb4-49">)</span>
<span id="cb4-50"></span>
<span id="cb4-51">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-5-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation" class="level3" data-number="0.19">
<h3 data-number="0.19" class="anchored" data-anchor-id="interpretation"><span class="header-section-number">0.19</span> Interpretation</h3>
<p>All populations began with: <img src="https://latex.codecogs.com/png.latex?p_0=0.5">.</p>
<p>Yet they diverged dramatically.</p>
<p>Some populations moved upward.</p>
<p>Some moved downward.</p>
<p>Some approached fixation.</p>
<p>Some approached extinction.</p>
<p>This illustrates a central lesson:</p>
<blockquote class="blockquote">
<p>Evolutionary outcomes can differ substantially even when populations start under identical conditions.</p>
</blockquote>
</section>
<section id="summary" class="level3" data-number="0.20">
<h3 data-number="0.20" class="anchored" data-anchor-id="summary"><span class="header-section-number">0.20</span> Summary</h3>
<p>In this first part we learned:</p>
<ul>
<li>What genetic drift is</li>
<li>Why finite populations matter</li>
<li>What fixation means</li>
<li>The Wright-Fisher model</li>
<li>Classical theorems of drift</li>
<li>Why small populations drift faster</li>
<li>How to simulate allele-frequency trajectories</li>
</ul>
<p>In Part 2 we will move beyond a single SNP and systematically investigate:</p>
<ul>
<li>Population size effects</li>
<li>Initial allele frequency effects</li>
<li>Fixation probability verification</li>
<li>Multiple SNP simulations</li>
<li>Sample size effects</li>
<li>Allele frequency spectra</li>
</ul>
</section>
<section id="experimental-exploration-of-genetic-drift" class="level3" data-number="0.21">
<h3 data-number="0.21" class="anchored" data-anchor-id="experimental-exploration-of-genetic-drift"><span class="header-section-number">0.21</span> Experimental Exploration of Genetic Drift</h3>
<p>In Part 1, we simulated a single SNP evolving under neutral genetic drift.</p>
<p>Now we move toward a more realistic population genetics framework by asking:</p>
<ul>
<li>What happens when population size changes?</li>
<li>What happens when initial allele frequency changes?</li>
<li>Can we experimentally verify the fixation theorem?</li>
<li>What happens when thousands of SNPs evolve simultaneously?</li>
<li>How does sample size affect allele frequency estimates?</li>
<li>How does drift reshape the allele frequency spectrum?</li>
</ul>
<p>These experiments mirror questions encountered in modern statistical genetics and genomics.</p>
</section>
<section id="experiment-1-effect-of-population-size" class="level3" data-number="0.22">
<h3 data-number="0.22" class="anchored" data-anchor-id="experiment-1-effect-of-population-size"><span class="header-section-number">0.22</span> Experiment 1: Effect of Population Size</h3>
<p>Recall the variance theorem:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AVar(p_%7Bt+1%7D%7Cp_t)%0A=%0A%5Cfrac%7Bp_t(1-p_t)%7D%7B2N%7D%0A"></p>
<p>The denominator contains population size:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%0A"></p>
<p>Therefore:</p>
<ul>
<li>Small populations should drift rapidly.</li>
<li>Large populations should drift slowly.</li>
</ul>
</section>
<section id="simulating-different-population-sizes" class="level3" data-number="0.23">
<h3 data-number="0.23" class="anchored" data-anchor-id="simulating-different-population-sizes"><span class="header-section-number">0.23</span> Simulating Different Population Sizes</h3>
<div id="71845885-4ec0-46ed-acf2-f35c5c4f9be7" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"></span>
<span id="cb5-2">population_sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb5-3">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb5-4">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>,</span>
<span id="cb5-5">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb5-6">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>,</span>
<span id="cb5-7">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span></span>
<span id="cb5-8">]</span>
<span id="cb5-9"></span>
<span id="cb5-10">plt.figure(figsize<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;">12</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>))</span>
<span id="cb5-11"></span>
<span id="cb5-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> N <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> population_sizes:</span>
<span id="cb5-13"></span>
<span id="cb5-14">    traj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb5-15">        N<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>N,</span>
<span id="cb5-16">        p0<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.5</span>,</span>
<span id="cb5-17">        generations<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;">200</span></span>
<span id="cb5-18">    )</span>
<span id="cb5-19"></span>
<span id="cb5-20">    plt.plot(</span>
<span id="cb5-21">        traj,</span>
<span id="cb5-22">        linewidth<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>
<span id="cb5-23">        label<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"N=</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="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb5-24">    )</span>
<span id="cb5-25"></span>
<span id="cb5-26">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Generation"</span>)</span>
<span id="cb5-27">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allele Frequency"</span>)</span>
<span id="cb5-28"></span>
<span id="cb5-29">plt.title(</span>
<span id="cb5-30">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Effect of Population Size on Genetic Drift"</span></span>
<span id="cb5-31">)</span>
<span id="cb5-32"></span>
<span id="cb5-33">plt.legend()</span>
<span id="cb5-34"></span>
<span id="cb5-35">plt.ylim(</span>
<span id="cb5-36">    <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.05</span>,</span>
<span id="cb5-37">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.05</span></span>
<span id="cb5-38">)</span>
<span id="cb5-39"></span>
<span id="cb5-40">plt.show()</span>
<span id="cb5-41"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-6-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-1" class="level3" data-number="0.24">
<h3 data-number="0.24" class="anchored" data-anchor-id="interpretation-1"><span class="header-section-number">0.24</span> Interpretation</h3>
<p>Notice the dramatic difference.</p>
<p>For:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN=20%0A"></p>
<p>the allele frequency may rapidly reach fixation or extinction.</p>
<p>For:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN=1000%0A"></p>
<p>the frequency remains close to its initial value.</p>
<p>This directly verifies the variance theorem.</p>
</section>
<section id="quantifying-drift-variability" class="level3" data-number="0.25">
<h3 data-number="0.25" class="anchored" data-anchor-id="quantifying-drift-variability"><span class="header-section-number">0.25</span> Quantifying Drift Variability</h3>
<p>Instead of looking at one trajectory, we can measure variance across many replicate populations.</p>
<div id="5c138c1c-c267-4b47-a7a3-1bbd05545b86" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">population_sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb6-2">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb6-3">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>,</span>
<span id="cb6-4">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb6-5">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>,</span>
<span id="cb6-6">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span></span>
<span id="cb6-7">]</span>
<span id="cb6-8"></span>
<span id="cb6-9">variances<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb6-10"></span>
<span id="cb6-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> N <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> population_sizes:</span>
<span id="cb6-12"></span>
<span id="cb6-13">    final_freqs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb6-14"></span>
<span id="cb6-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <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>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>):</span>
<span id="cb6-16"></span>
<span id="cb6-17">        traj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb6-18">            N<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>N,</span>
<span id="cb6-19">            p0<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.5</span>,</span>
<span id="cb6-20">            generations<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;">100</span></span>
<span id="cb6-21">        )</span>
<span id="cb6-22"></span>
<span id="cb6-23">        final_freqs.append(</span>
<span id="cb6-24">            traj[<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="cb6-25">        )</span>
<span id="cb6-26"></span>
<span id="cb6-27">    variances.append(</span>
<span id="cb6-28">        np.var(final_freqs)</span>
<span id="cb6-29">    )</span></code></pre></div></div>
</div>
<div id="9babecb3-1afe-429f-850b-73bb190a60cf" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">plt.figure(figsize<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>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb7-2"></span>
<span id="cb7-3">plt.plot(</span>
<span id="cb7-4">    population_sizes,</span>
<span id="cb7-5">    variances,</span>
<span id="cb7-6">    marker<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;">"o"</span>,</span>
<span id="cb7-7">    linewidth<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;">3</span></span>
<span id="cb7-8">)</span>
<span id="cb7-9"></span>
<span id="cb7-10">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Population Size"</span>)</span>
<span id="cb7-11">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Variance of Final Allele Frequency"</span>)</span>
<span id="cb7-12"></span>
<span id="cb7-13">plt.title(</span>
<span id="cb7-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Drift Variance Decreases With Population Size"</span></span>
<span id="cb7-15">)</span>
<span id="cb7-16"></span>
<span id="cb7-17">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-8-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="experiment-2-initial-allele-frequency" class="level3" data-number="0.26">
<h3 data-number="0.26" class="anchored" data-anchor-id="experiment-2-initial-allele-frequency"><span class="header-section-number">0.26</span> Experiment 2: Initial Allele Frequency</h3>
<p>The fixation theorem states:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(Fixation)=p_0%0A"></p>
<p>where, <img src="https://latex.codecogs.com/png.latex?p_0"> is the initial allele frequency.</p>
<p>We first visualize trajectories starting from different frequencies.</p>
<div id="0cfc7639-8c33-4f21-a5d1-e7dceb0ff64c" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">starting_frequencies <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb8-2">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="cb8-3">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>,</span>
<span id="cb8-4">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>,</span>
<span id="cb8-5">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>,</span>
<span id="cb8-6">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span></span>
<span id="cb8-7">]</span>
<span id="cb8-8"></span>
<span id="cb8-9">plt.figure(figsize<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;">12</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>))</span>
<span id="cb8-10"></span>
<span id="cb8-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p0 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> starting_frequencies:</span>
<span id="cb8-12"></span>
<span id="cb8-13">    traj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb8-14">        N<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;">100</span>,</span>
<span id="cb8-15">        p0<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p0,</span>
<span id="cb8-16">        generations<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;">200</span></span>
<span id="cb8-17">    )</span>
<span id="cb8-18"></span>
<span id="cb8-19">    plt.plot(</span>
<span id="cb8-20">        traj,</span>
<span id="cb8-21">        label<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"p0=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>p0<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>
<span id="cb8-22">    )</span>
<span id="cb8-23"></span>
<span id="cb8-24">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Generation"</span>)</span>
<span id="cb8-25">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allele Frequency"</span>)</span>
<span id="cb8-26"></span>
<span id="cb8-27">plt.title(</span>
<span id="cb8-28">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Effect of Initial Allele Frequency"</span></span>
<span id="cb8-29">)</span>
<span id="cb8-30"></span>
<span id="cb8-31">plt.legend()</span>
<span id="cb8-32"></span>
<span id="cb8-33">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-9-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-2" class="level3" data-number="0.27">
<h3 data-number="0.27" class="anchored" data-anchor-id="interpretation-2"><span class="header-section-number">0.27</span> Interpretation</h3>
<p>Alleles beginning near <img src="https://latex.codecogs.com/png.latex?p=1"> have a much greater chance of fixation.</p>
<p>Alleles beginning near <img src="https://latex.codecogs.com/png.latex?p=0"></p>
<p>have a much greater chance of loss.</p>
</section>
<section id="experiment-3-verifying-the-fixation-theorem" class="level3" data-number="0.28">
<h3 data-number="0.28" class="anchored" data-anchor-id="experiment-3-verifying-the-fixation-theorem"><span class="header-section-number">0.28</span> Experiment 3: Verifying the Fixation Theorem</h3>
<p>One of the most elegant results in population genetics states <img src="https://latex.codecogs.com/png.latex?P(Fixation)=p_0"> .</p>
<p>We now verify this experimentally.</p>
<div id="4787396c-735a-4b04-ab1d-046262f1bb04" class="cell" data-execution_count="9">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> estimate_fixation_probability(</span>
<span id="cb9-2">    p0,</span>
<span id="cb9-3">    N<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;">100</span>,</span>
<span id="cb9-4">    generations<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;">1000</span>,</span>
<span id="cb9-5">    n_replicates<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;">1000</span></span>
<span id="cb9-6">):</span>
<span id="cb9-7"></span>
<span id="cb9-8">    fixation_count<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="cb9-9"></span>
<span id="cb9-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <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_replicates):</span>
<span id="cb9-11"></span>
<span id="cb9-12">        traj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb9-13">            N<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>N,</span>
<span id="cb9-14">            p0<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p0,</span>
<span id="cb9-15">            generations<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>generations</span>
<span id="cb9-16">        )</span>
<span id="cb9-17"></span>
<span id="cb9-18">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> traj[<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="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="cb9-19">            fixation_count <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="cb9-20"></span>
<span id="cb9-21">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fixation_count<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>n_replicates</span>
<span id="cb9-22"></span>
<span id="cb9-23">p0_values <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.arange(</span>
<span id="cb9-24">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>,</span>
<span id="cb9-25">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>,</span>
<span id="cb9-26">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span></span>
<span id="cb9-27">)</span>
<span id="cb9-28"></span>
<span id="cb9-29">estimated_probs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb9-30"></span>
<span id="cb9-31"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p0 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> p0_values:</span>
<span id="cb9-32"></span>
<span id="cb9-33">    estimated_probs.append(</span>
<span id="cb9-34">        estimate_fixation_probability(</span>
<span id="cb9-35">            p0<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p0,</span>
<span id="cb9-36">            N<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;">100</span>,</span>
<span id="cb9-37">            generations<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;">1000</span>,</span>
<span id="cb9-38">            n_replicates<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="cb9-39">        )</span>
<span id="cb9-40">    )</span>
<span id="cb9-41"></span></code></pre></div></div>
</div>
<div id="941f40c0-4650-418f-a93d-019beaf7559d" class="cell" data-execution_count="10">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">plt.figure(figsize<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;">8</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb10-2"></span>
<span id="cb10-3">plt.plot(</span>
<span id="cb10-4">    p0_values,</span>
<span id="cb10-5">    p0_values,</span>
<span id="cb10-6">    linewidth<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;">3</span>,</span>
<span id="cb10-7">    label<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;">"Theory"</span></span>
<span id="cb10-8">)</span>
<span id="cb10-9"></span>
<span id="cb10-10">plt.scatter(</span>
<span id="cb10-11">    p0_values,</span>
<span id="cb10-12">    estimated_probs,</span>
<span id="cb10-13">    s<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;">70</span>,</span>
<span id="cb10-14">    label<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;">"Simulation"</span></span>
<span id="cb10-15">)</span>
<span id="cb10-16"></span>
<span id="cb10-17">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Initial Frequency"</span>)</span>
<span id="cb10-18">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fixation Probability"</span>)</span>
<span id="cb10-19"></span>
<span id="cb10-20">plt.title(</span>
<span id="cb10-21">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Experimental Verification of the Fixation Theorem"</span></span>
<span id="cb10-22">)</span>
<span id="cb10-23"></span>
<span id="cb10-24">plt.legend()</span>
<span id="cb10-25"></span>
<span id="cb10-26">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-11-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-3" class="level3" data-number="0.29">
<h3 data-number="0.29" class="anchored" data-anchor-id="interpretation-3"><span class="header-section-number">0.29</span> Interpretation</h3>
<p>The simulation closely follows the theoretical prediction:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(Fixation)=p_0%0A"></p>
<p>This is one of the most important theorems in neutral evolution.</p>
</section>
<section id="experiment-4-multiple-snp-simulation" class="level3" data-number="0.30">
<h3 data-number="0.30" class="anchored" data-anchor-id="experiment-4-multiple-snp-simulation"><span class="header-section-number">0.30</span> Experiment 4: Multiple SNP Simulation</h3>
<p>Real genomes contain millions of SNPs.</p>
<p>Instead of tracking a single locus, we simulate many SNPs simultaneously.</p>
<div id="403c7a6a-50f1-4d67-8845-0de2e730bd3b" class="cell" data-execution_count="11">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Creating 1,000 Independent SNPs</span></span>
<span id="cb11-2"></span>
<span id="cb11-3"></span>
<span id="cb11-4">n_snps <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;">1000</span></span>
<span id="cb11-5"></span>
<span id="cb11-6">initial_freqs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.uniform(</span>
<span id="cb11-7">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>,</span>
<span id="cb11-8">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>,</span>
<span id="cb11-9">    n_snps</span>
<span id="cb11-10">)</span>
<span id="cb11-11"></span>
<span id="cb11-12">final_freqs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb11-13"></span>
<span id="cb11-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p0 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> initial_freqs:</span>
<span id="cb11-15"></span>
<span id="cb11-16">    traj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb11-17">        N<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;">100</span>,</span>
<span id="cb11-18">        p0<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p0,</span>
<span id="cb11-19">        generations<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;">200</span></span>
<span id="cb11-20">    )</span>
<span id="cb11-21"></span>
<span id="cb11-22">    final_freqs.append(</span>
<span id="cb11-23">        traj[<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="cb11-24">    )</span>
<span id="cb11-25"></span>
<span id="cb11-26"></span>
<span id="cb11-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Visualizing Frequency Changes</span></span>
<span id="cb11-28"></span>
<span id="cb11-29">plt.figure(figsize<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;">12</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb11-30"></span>
<span id="cb11-31">plt.hist(</span>
<span id="cb11-32">    initial_freqs,</span>
<span id="cb11-33">    bins<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;">30</span>,</span>
<span id="cb11-34">    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.6</span>,</span>
<span id="cb11-35">    label<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;">"Initial Frequencies"</span></span>
<span id="cb11-36">)</span>
<span id="cb11-37"></span>
<span id="cb11-38">plt.hist(</span>
<span id="cb11-39">    final_freqs,</span>
<span id="cb11-40">    bins<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;">30</span>,</span>
<span id="cb11-41">    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.6</span>,</span>
<span id="cb11-42">    label<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;">"Final Frequencies"</span></span>
<span id="cb11-43">)</span>
<span id="cb11-44"></span>
<span id="cb11-45">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allele Frequency"</span>)</span>
<span id="cb11-46">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of SNPs"</span>)</span>
<span id="cb11-47"></span>
<span id="cb11-48">plt.title(</span>
<span id="cb11-49">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genetic Drift Reshapes the Frequency Spectrum"</span></span>
<span id="cb11-50">)</span>
<span id="cb11-51"></span>
<span id="cb11-52">plt.legend()</span>
<span id="cb11-53"></span>
<span id="cb11-54">plt.show()</span>
<span id="cb11-55"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-12-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-4" class="level3" data-number="0.31">
<h3 data-number="0.31" class="anchored" data-anchor-id="interpretation-4"><span class="header-section-number">0.31</span> Interpretation</h3>
<p>Initially, frequencies were nearly uniform.</p>
<p>After drift:</p>
<ul>
<li>More SNPs accumulate near 0</li>
<li>More SNPs accumulate near 1</li>
<li>Intermediate frequencies become less common</li>
</ul>
<p>This is a hallmark of neutral evolution.</p>
</section>
<section id="experiment-5-snp-loss-and-fixation" class="level3" data-number="0.32">
<h3 data-number="0.32" class="anchored" data-anchor-id="experiment-5-snp-loss-and-fixation"><span class="header-section-number">0.32</span> Experiment 5: SNP Loss and Fixation</h3>
<p>How many SNPs become fixed or lost?</p>
<div id="ba39feea-b0a1-433e-afe6-dce75f7ca5ce" class="cell" data-execution_count="12">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"></span>
<span id="cb12-2"></span>
<span id="cb12-3">lost<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="cb12-4">fixed<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="cb12-5"></span>
<span id="cb12-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> final_freqs:</span>
<span id="cb12-7"></span>
<span id="cb12-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> p <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="cb12-9">        lost <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="cb12-10"></span>
<span id="cb12-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> p <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="cb12-12">        fixed <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="cb12-13"></span>
<span id="cb12-14"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lost SNPs:"</span>, lost)</span>
<span id="cb12-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fixed SNPs:"</span>, fixed)</span>
<span id="cb12-16"></span>
<span id="cb12-17"></span>
<span id="cb12-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Visualization</span></span>
<span id="cb12-19"></span>
<span id="cb12-20"></span>
<span id="cb12-21">categories <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb12-22">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lost"</span>,</span>
<span id="cb12-23">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fixed"</span>,</span>
<span id="cb12-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Segregating"</span></span>
<span id="cb12-25">]</span>
<span id="cb12-26"></span>
<span id="cb12-27">counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb12-28">    lost,</span>
<span id="cb12-29">    fixed,</span>
<span id="cb12-30">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(final_freqs)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>lost<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>fixed</span>
<span id="cb12-31">]</span>
<span id="cb12-32"></span>
<span id="cb12-33">plt.figure(figsize<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;">8</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb12-34"></span>
<span id="cb12-35">plt.bar(</span>
<span id="cb12-36">    categories,</span>
<span id="cb12-37">    counts</span>
<span id="cb12-38">)</span>
<span id="cb12-39"></span>
<span id="cb12-40">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of SNPs"</span>)</span>
<span id="cb12-41"></span>
<span id="cb12-42">plt.title(</span>
<span id="cb12-43">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fate of SNPs After Drift"</span></span>
<span id="cb12-44">)</span>
<span id="cb12-45"></span>
<span id="cb12-46">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Lost SNPs: 313
Fixed SNPs: 285</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-13-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="experiment-6-number-of-snps-matters" class="level3" data-number="0.33">
<h3 data-number="0.33" class="anchored" data-anchor-id="experiment-6-number-of-snps-matters"><span class="header-section-number">0.33</span> Experiment 6: Number of SNPs Matters</h3>
<p>Now repeat the experiment using increasingly larger numbers of SNPs.</p>
<div id="39c5f58e-038b-4dcc-a4a0-d6d6adb0f488" class="cell" data-execution_count="13">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"></span>
<span id="cb14-2">snp_counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb14-3">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb14-4">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>,</span>
<span id="cb14-5">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>,</span>
<span id="cb14-6">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span></span>
<span id="cb14-7">]</span>
<span id="cb14-8"></span>
<span id="cb14-9">fixed_counts<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb14-10">lost_counts<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb14-11"></span>
<span id="cb14-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n_snps <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> snp_counts:</span>
<span id="cb14-13"></span>
<span id="cb14-14">    fixed<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="cb14-15">    lost<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="cb14-16"></span>
<span id="cb14-17">    freqs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.random.uniform(</span>
<span id="cb14-18">        <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>,</span>
<span id="cb14-19">        <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>,</span>
<span id="cb14-20">        n_snps</span>
<span id="cb14-21">    )</span>
<span id="cb14-22"></span>
<span id="cb14-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p0 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> freqs:</span>
<span id="cb14-24"></span>
<span id="cb14-25">        traj<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>simulate_drift(</span>
<span id="cb14-26">            N<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;">50</span>,</span>
<span id="cb14-27">            p0<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p0,</span>
<span id="cb14-28">            generations<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;">300</span></span>
<span id="cb14-29">        )</span>
<span id="cb14-30"></span>
<span id="cb14-31">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> traj[<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="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="cb14-32">            fixed <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="cb14-33"></span>
<span id="cb14-34">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> traj[<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="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="cb14-35">            lost <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="cb14-36"></span>
<span id="cb14-37">    fixed_counts.append(fixed)</span>
<span id="cb14-38">    lost_counts.append(lost)</span>
<span id="cb14-39"></span>
<span id="cb14-40">plt.figure(figsize<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>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb14-41"></span>
<span id="cb14-42">plt.plot(</span>
<span id="cb14-43">    snp_counts,</span>
<span id="cb14-44">    fixed_counts,</span>
<span id="cb14-45">    marker<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;">"o"</span>,</span>
<span id="cb14-46">    linewidth<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;">3</span>,</span>
<span id="cb14-47">    label<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;">"Fixed"</span></span>
<span id="cb14-48">)</span>
<span id="cb14-49"></span>
<span id="cb14-50">plt.plot(</span>
<span id="cb14-51">    snp_counts,</span>
<span id="cb14-52">    lost_counts,</span>
<span id="cb14-53">    marker<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;">"o"</span>,</span>
<span id="cb14-54">    linewidth<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;">3</span>,</span>
<span id="cb14-55">    label<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;">"Lost"</span></span>
<span id="cb14-56">)</span>
<span id="cb14-57"></span>
<span id="cb14-58">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of SNPs"</span>)</span>
<span id="cb14-59">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Count"</span>)</span>
<span id="cb14-60"></span>
<span id="cb14-61">plt.title(</span>
<span id="cb14-62">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genome-Wide Consequences of Drift"</span></span>
<span id="cb14-63">)</span>
<span id="cb14-64"></span>
<span id="cb14-65">plt.legend()</span>
<span id="cb14-66"></span>
<span id="cb14-67">plt.show()</span>
<span id="cb14-68"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-14-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-5" class="level3" data-number="0.34">
<h3 data-number="0.34" class="anchored" data-anchor-id="interpretation-5"><span class="header-section-number">0.34</span> Interpretation</h3>
<p>As the number of SNPs increases:</p>
<ul>
<li>More variants become fixed</li>
<li>More variants become lost</li>
<li>Overall diversity declines</li>
</ul>
</section>
<section id="experiment-7-sampling-error-versus-genetic-drift" class="level3" data-number="0.35">
<h3 data-number="0.35" class="anchored" data-anchor-id="experiment-7-sampling-error-versus-genetic-drift"><span class="header-section-number">0.35</span> Experiment 7: Sampling Error Versus Genetic Drift</h3>
<p>In GWAS we rarely observe the entire population.</p>
<p>Instead we estimate allele frequencies from samples.</p>
<p>Suppose the true frequency is <img src="https://latex.codecogs.com/png.latex?p=0.30">.</p>
</section>
<section id="simulating-sampling-error" class="level3" data-number="0.36">
<h3 data-number="0.36" class="anchored" data-anchor-id="simulating-sampling-error"><span class="header-section-number">0.36</span> Simulating Sampling Error</h3>
<div id="c55ee867-bfc0-41bd-a650-e556f491fa4f" class="cell" data-execution_count="14">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"></span>
<span id="cb15-2">true_frequency <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.30</span></span>
<span id="cb15-3"></span>
<span id="cb15-4">sample_sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb15-5">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb15-6">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>,</span>
<span id="cb15-7">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb15-8">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>,</span>
<span id="cb15-9">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>,</span>
<span id="cb15-10">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span></span>
<span id="cb15-11">]</span>
<span id="cb15-12"></span>
<span id="cb15-13">sampling_std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb15-14"></span>
<span id="cb15-15"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sample_sizes:</span>
<span id="cb15-16"></span>
<span id="cb15-17">    estimates<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb15-18"></span>
<span id="cb15-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <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>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>):</span>
<span id="cb15-20"></span>
<span id="cb15-21">        count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.binomial(</span>
<span id="cb15-22">            n,</span>
<span id="cb15-23">            true_frequency</span>
<span id="cb15-24">        )</span>
<span id="cb15-25"></span>
<span id="cb15-26">        estimates.append(</span>
<span id="cb15-27">            count<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>n</span>
<span id="cb15-28">        )</span>
<span id="cb15-29"></span>
<span id="cb15-30">    sampling_std.append(</span>
<span id="cb15-31">        np.std(estimates)</span>
<span id="cb15-32">    )</span>
<span id="cb15-33"></span>
<span id="cb15-34">plt.figure(figsize<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>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb15-35"></span>
<span id="cb15-36">plt.plot(</span>
<span id="cb15-37">    sample_sizes,</span>
<span id="cb15-38">    sampling_std,</span>
<span id="cb15-39">    marker<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;">"o"</span>,</span>
<span id="cb15-40">    linewidth<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;">3</span></span>
<span id="cb15-41">)</span>
<span id="cb15-42"></span>
<span id="cb15-43">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sample Size"</span>)</span>
<span id="cb15-44">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Standard Deviation"</span>)</span>
<span id="cb15-45"></span>
<span id="cb15-46">plt.title(</span>
<span id="cb15-47">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sampling Error Decreases With Sample Size"</span></span>
<span id="cb15-48">)</span>
<span id="cb15-49"></span>
<span id="cb15-50">plt.show()</span>
<span id="cb15-51"></span>
<span id="cb15-52"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-15-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-6" class="level3" data-number="0.37">
<h3 data-number="0.37" class="anchored" data-anchor-id="interpretation-6"><span class="header-section-number">0.37</span> Interpretation</h3>
<p>Larger studies produce more precise allele frequency estimates.</p>
<p>This randomness is not genetic drift.</p>
<p>Instead it is statistical sampling error.</p>
</section>
<section id="genetic-drift-vs-sampling-error" class="level3" data-number="0.38">
<h3 data-number="0.38" class="anchored" data-anchor-id="genetic-drift-vs-sampling-error"><span class="header-section-number">0.38</span> Genetic Drift vs Sampling Error</h3>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Genetic Drift</th>
<th>Sampling Error</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Biological process</td>
<td>Measurement process</td>
</tr>
<tr class="even">
<td>Occurs across generations</td>
<td>Occurs during data collection</td>
</tr>
<tr class="odd">
<td>Changes true frequency</td>
<td>Changes estimated frequency</td>
</tr>
<tr class="even">
<td>Evolutionary phenomenon</td>
<td>Statistical phenomenon</td>
</tr>
</tbody>
</table>
<p>Understanding this distinction is essential in GWAS and population genetics.</p>
</section>
<section id="experiment-8-distribution-of-frequency-estimates" class="level3" data-number="0.39">
<h3 data-number="0.39" class="anchored" data-anchor-id="experiment-8-distribution-of-frequency-estimates"><span class="header-section-number">0.39</span> Experiment 8: Distribution of Frequency Estimates</h3>
<div id="090175a5-6ec4-4226-8081-388f92084faa" class="cell" data-execution_count="15">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"></span>
<span id="cb16-2">sample_size <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;">50</span></span>
<span id="cb16-3"></span>
<span id="cb16-4">estimates<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb16-5"></span>
<span id="cb16-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <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>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000</span>):</span>
<span id="cb16-7"></span>
<span id="cb16-8">    count<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.random.binomial(</span>
<span id="cb16-9">        sample_size,</span>
<span id="cb16-10">        true_frequency</span>
<span id="cb16-11">    )</span>
<span id="cb16-12"></span>
<span id="cb16-13">    estimates.append(</span>
<span id="cb16-14">        count<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>sample_size</span>
<span id="cb16-15">    )</span>
<span id="cb16-16"></span>
<span id="cb16-17">plt.figure(figsize<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>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb16-18"></span>
<span id="cb16-19">plt.hist(</span>
<span id="cb16-20">    estimates,</span>
<span id="cb16-21">    bins<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;">40</span></span>
<span id="cb16-22">)</span>
<span id="cb16-23"></span>
<span id="cb16-24">plt.axvline(</span>
<span id="cb16-25">    true_frequency,</span>
<span id="cb16-26">    linestyle<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;">"--"</span></span>
<span id="cb16-27">)</span>
<span id="cb16-28"></span>
<span id="cb16-29">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Estimated Frequency"</span>)</span>
<span id="cb16-30">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Count"</span>)</span>
<span id="cb16-31"></span>
<span id="cb16-32">plt.title(</span>
<span id="cb16-33">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sampling Distribution of Allele Frequency Estimates"</span></span>
<span id="cb16-34">)</span>
<span id="cb16-35"></span>
<span id="cb16-36">plt.show()</span>
<span id="cb16-37"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-16-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-7" class="level3" data-number="0.40">
<h3 data-number="0.40" class="anchored" data-anchor-id="interpretation-7"><span class="header-section-number">0.40</span> Interpretation</h3>
<p>Even though the true frequency remains fixed at:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=0.30%0A"></p>
<p>individual samples produce different estimates.</p>
<p>This is exactly why larger cohorts improve statistical power.</p>
</section>
<section id="summary-1" class="level3" data-number="0.41">
<h3 data-number="0.41" class="anchored" data-anchor-id="summary-1"><span class="header-section-number">0.41</span> Summary</h3>
<p>In this section we experimentally demonstrated:</p>
<ol type="1">
<li>Small populations drift faster.</li>
<li>Large populations are more stable.</li>
<li>Fixation probability equals starting frequency.</li>
<li>Drift pushes SNPs toward fixation and extinction.</li>
<li>Diversity decreases across the genome.</li>
<li>Sample size affects precision of allele-frequency estimation.</li>
<li>Sampling error and genetic drift are fundamentally different processes.</li>
</ol>
<p>In Part 3 we will move to:</p>
<ul>
<li>Genome-wide simulations</li>
<li>Heterozygosity decay</li>
<li>Effective population size</li>
<li>Bottlenecks</li>
<li>Founder effects</li>
<li>Population structure</li>
<li>GWAS implications</li>
<li>Modern statistical genetics applications</li>
</ul>
</section>
<section id="genome-wide-consequences-of-genetic-drift" class="level3" data-number="0.42">
<h3 data-number="0.42" class="anchored" data-anchor-id="genome-wide-consequences-of-genetic-drift"><span class="header-section-number">0.42</span> Genome-Wide Consequences of Genetic Drift</h3>
<p>So far we have studied drift at the level of individual SNPs.</p>
<p>Real genomes contain millions of variants.</p>
<p>Over evolutionary time, drift acts simultaneously on all of them.</p>
<p>The cumulative effect produces:</p>
<ul>
<li>Loss of genetic diversity</li>
<li>Population differentiation</li>
<li>Founder effects</li>
<li>Population bottlenecks</li>
<li>Changes in allele frequency spectra</li>
</ul>
<p>Many patterns observed in modern genomics can be understood through drift alone.</p>
</section>
<section id="heterozygosity" class="level3" data-number="0.43">
<h3 data-number="0.43" class="anchored" data-anchor-id="heterozygosity"><span class="header-section-number">0.43</span> Heterozygosity</h3>
<p>One of the most important measures of genetic diversity is heterozygosity.</p>
<p>For a biallelic SNP:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH%20=%202p(1-p)%0A"></p>
<p>where:</p>
<ul>
<li>(p) = frequency of allele A</li>
<li>(1-p) = frequency of allele a</li>
</ul>
</section>
<section id="maximum-heterozygosity" class="level3" data-number="0.44">
<h3 data-number="0.44" class="anchored" data-anchor-id="maximum-heterozygosity"><span class="header-section-number">0.44</span> Maximum Heterozygosity</h3>
<p>The maximum occurs when:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=0.5%0A"></p>
<p>because:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH=2(0.5)(0.5)=0.5%0A"></p>
<p>The minimum occurs when:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=0%0A"></p>
<p>or</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=1%0A"></p>
<p>because:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH=0%0A"></p>
<p>At fixation, all diversity disappears.</p>
</section>
<section id="theoretical-decay-of-heterozygosity" class="level3" data-number="0.45">
<h3 data-number="0.45" class="anchored" data-anchor-id="theoretical-decay-of-heterozygosity"><span class="header-section-number">0.45</span> Theoretical Decay of Heterozygosity</h3>
<p>One of the classical results of population genetics is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH_t%0A=%0AH_0%0A%5Cleft(%0A1-%5Cfrac%7B1%7D%7B2N%7D%0A%5Cright)%5Et%0A"></p>
<p>where:</p>
<ul>
<li>(H_0) = initial heterozygosity</li>
<li>(N) = population size</li>
<li>(t) = generations</li>
</ul>
</section>
<section id="simulating-heterozygosity-decay" class="level3" data-number="0.46">
<h3 data-number="0.46" class="anchored" data-anchor-id="simulating-heterozygosity-decay"><span class="header-section-number">0.46</span> Simulating Heterozygosity Decay</h3>
<div id="8d93f388-d905-4781-9ef8-56329c284dad" class="cell" data-execution_count="16">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"></span>
<span id="cb17-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> heterozygosity_decay(</span>
<span id="cb17-3">    H0,</span>
<span id="cb17-4">    N,</span>
<span id="cb17-5">    generations</span>
<span id="cb17-6">):</span>
<span id="cb17-7"></span>
<span id="cb17-8">    t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.arange(</span>
<span id="cb17-9">        generations<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="cb17-10">    )</span>
<span id="cb17-11"></span>
<span id="cb17-12">    Ht <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> H0 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (</span>
<span id="cb17-13">        <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <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="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>N)</span>
<span id="cb17-14">    )<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>t</span>
<span id="cb17-15"></span>
<span id="cb17-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> t, Ht</span>
<span id="cb17-17"></span>
<span id="cb17-18">population_sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb17-19">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb17-20">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb17-21">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>,</span>
<span id="cb17-22">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span></span>
<span id="cb17-23">]</span>
<span id="cb17-24"></span>
<span id="cb17-25">plt.figure(figsize<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;">12</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb17-26"></span>
<span id="cb17-27"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> N <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> population_sizes:</span>
<span id="cb17-28"></span>
<span id="cb17-29">    t,Ht <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> heterozygosity_decay(</span>
<span id="cb17-30">        H0<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.5</span>,</span>
<span id="cb17-31">        N<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>N,</span>
<span id="cb17-32">        generations<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="cb17-33">    )</span>
<span id="cb17-34"></span>
<span id="cb17-35">    plt.plot(</span>
<span id="cb17-36">        t,</span>
<span id="cb17-37">        Ht,</span>
<span id="cb17-38">        linewidth<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;">3</span>,</span>
<span id="cb17-39">        label<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"N=</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="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb17-40">    )</span>
<span id="cb17-41"></span>
<span id="cb17-42">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Generation"</span>)</span>
<span id="cb17-43">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expected Heterozygosity"</span>)</span>
<span id="cb17-44"></span>
<span id="cb17-45">plt.title(</span>
<span id="cb17-46">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Loss of Genetic Diversity Through Drift"</span></span>
<span id="cb17-47">)</span>
<span id="cb17-48"></span>
<span id="cb17-49">plt.legend()</span>
<span id="cb17-50"></span>
<span id="cb17-51">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-17-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-8" class="level3" data-number="0.47">
<h3 data-number="0.47" class="anchored" data-anchor-id="interpretation-8"><span class="header-section-number">0.47</span> Interpretation</h3>
<p>Small populations lose diversity rapidly.</p>
<p>Large populations retain diversity for much longer periods.</p>
<p>This is one reason conservation biologists worry about endangered populations.</p>
</section>
<section id="effective-population-size" class="level3" data-number="0.48">
<h3 data-number="0.48" class="anchored" data-anchor-id="effective-population-size"><span class="header-section-number">0.48</span> Effective Population Size</h3>
<p>A critical concept in population genetics is:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN_e%0A"></p>
<p>the effective population size.</p>
<section id="census-size-vs-effective-size" class="level4" data-number="0.48.1">
<h4 data-number="0.48.1" class="anchored" data-anchor-id="census-size-vs-effective-size"><span class="header-section-number">0.48.1</span> Census Size vs Effective Size</h4>
<p>Census size:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%0A"></p>
<p>represents the number of individuals.</p>
<p>Effective population size:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN_e%0A"></p>
<p>represents the size of an ideal population that experiences the same amount of drift.</p>
<p>Usually:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN_e%20%3C%20N%0A"></p>
</section>
</section>
<section id="why-is-effective-population-size-smaller" class="level3" data-number="0.49">
<h3 data-number="0.49" class="anchored" data-anchor-id="why-is-effective-population-size-smaller"><span class="header-section-number">0.49</span> Why is Effective Population Size Smaller?</h3>
<p>Real populations violate Wright-Fisher assumptions:</p>
<ul>
<li>Unequal family sizes</li>
<li>Population structure</li>
<li>Sex imbalance</li>
<li>Bottlenecks</li>
<li>Selection</li>
</ul>
<p>All of these increase drift.</p>
</section>
<section id="why-statistical-geneticists-care-about-ne" class="level3" data-number="0.50">
<h3 data-number="0.50" class="anchored" data-anchor-id="why-statistical-geneticists-care-about-ne"><span class="header-section-number">0.50</span> Why Statistical Geneticists Care About Ne</h3>
<p>Many quantities depend on:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN_e%0A"></p>
<p>including:</p>
<ul>
<li>LD decay</li>
<li>Drift strength</li>
<li>Coalescent times</li>
<li>Polygenic adaptation</li>
<li>Demographic inference</li>
</ul>
</section>
<section id="population-bottlenecks" class="level3" data-number="0.51">
<h3 data-number="0.51" class="anchored" data-anchor-id="population-bottlenecks"><span class="header-section-number">0.51</span> Population Bottlenecks</h3>
<p>A bottleneck occurs when population size suddenly decreases.</p>
<p>Examples include:</p>
<ul>
<li>Natural disasters</li>
<li>Famine</li>
<li>Disease outbreaks</li>
<li>Founder migrations</li>
</ul>
</section>
<section id="bottleneck-simulation" class="level3" data-number="0.52">
<h3 data-number="0.52" class="anchored" data-anchor-id="bottleneck-simulation"><span class="header-section-number">0.52</span> Bottleneck Simulation</h3>
<div id="e486cf2d-f4be-487b-ac46-451480eddd28" class="cell" data-execution_count="17">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"></span>
<span id="cb18-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> simulate_bottleneck(</span>
<span id="cb18-3">    p0<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.5</span>,</span>
<span id="cb18-4">    generations_before<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;">50</span>,</span>
<span id="cb18-5">    generations_bottleneck<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;">20</span>,</span>
<span id="cb18-6">    generations_after<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;">100</span>,</span>
<span id="cb18-7">    N_before<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;">1000</span>,</span>
<span id="cb18-8">    N_bottleneck<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;">20</span>,</span>
<span id="cb18-9">    N_after<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;">1000</span></span>
<span id="cb18-10">):</span>
<span id="cb18-11"></span>
<span id="cb18-12">    p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> p0</span>
<span id="cb18-13"></span>
<span id="cb18-14">    trajectory<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[p]</span>
<span id="cb18-15"></span>
<span id="cb18-16">    schedule <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb18-17">        [N_before]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>generations_before <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-18">        [N_bottleneck]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>generations_bottleneck <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-19">        [N_after]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>generations_after</span>
<span id="cb18-20">    )</span>
<span id="cb18-21"></span>
<span id="cb18-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> N <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> schedule:</span>
<span id="cb18-23"></span>
<span id="cb18-24">        count<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.random.binomial(</span>
<span id="cb18-25">            <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>N,</span>
<span id="cb18-26">            p</span>
<span id="cb18-27">        )</span>
<span id="cb18-28"></span>
<span id="cb18-29">        p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>count<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>N)</span>
<span id="cb18-30"></span>
<span id="cb18-31">        trajectory.append(p)</span>
<span id="cb18-32"></span>
<span id="cb18-33">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.array(trajectory)</span>
<span id="cb18-34"></span>
<span id="cb18-35">traj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_bottleneck()</span>
<span id="cb18-36"></span>
<span id="cb18-37">plt.figure(figsize<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;">12</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb18-38"></span>
<span id="cb18-39">plt.plot(</span>
<span id="cb18-40">    traj,</span>
<span id="cb18-41">    linewidth<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;">3</span></span>
<span id="cb18-42">)</span>
<span id="cb18-43"></span>
<span id="cb18-44">plt.axvspan(</span>
<span id="cb18-45">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>,</span>
<span id="cb18-46">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">70</span>,</span>
<span id="cb18-47">    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>
<span id="cb18-48">    label<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;">"Bottleneck"</span></span>
<span id="cb18-49">)</span>
<span id="cb18-50"></span>
<span id="cb18-51">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Generation"</span>)</span>
<span id="cb18-52">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allele Frequency"</span>)</span>
<span id="cb18-53"></span>
<span id="cb18-54">plt.title(</span>
<span id="cb18-55">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Population Bottleneck"</span></span>
<span id="cb18-56">)</span>
<span id="cb18-57"></span>
<span id="cb18-58">plt.legend()</span>
<span id="cb18-59"></span>
<span id="cb18-60">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-18-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-9" class="level3" data-number="0.53">
<h3 data-number="0.53" class="anchored" data-anchor-id="interpretation-9"><span class="header-section-number">0.53</span> Interpretation</h3>
<p>Most frequency changes occur during the bottleneck period.</p>
<p>This happens because:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AN%0A"></p>
<p>temporarily becomes very small.</p>
<section id="founder-effects" class="level4" data-number="0.53.1">
<h4 data-number="0.53.1" class="anchored" data-anchor-id="founder-effects"><span class="header-section-number">0.53.1</span> Founder Effects</h4>
<p>A founder effect is a special case of drift.</p>
<p>A small group leaves a large population and establishes a new population.</p>
<p>The new population contains only a subset of the original genetic variation.</p>
</section>
<section id="founder-effect-simulation" class="level4" data-number="0.53.2">
<h4 data-number="0.53.2" class="anchored" data-anchor-id="founder-effect-simulation"><span class="header-section-number">0.53.2</span> Founder Effect Simulation</h4>
<div id="4fcbd79b-45c3-4497-ab37-4d715cb4b805" class="cell" data-execution_count="18">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"></span>
<span id="cb19-2">source_population <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.uniform(</span>
<span id="cb19-3">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>,</span>
<span id="cb19-4">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>,</span>
<span id="cb19-5">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span></span>
<span id="cb19-6">)</span>
<span id="cb19-7"></span>
<span id="cb19-8">founder_population <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.choice(</span>
<span id="cb19-9">    source_population,</span>
<span id="cb19-10">    size<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;">200</span>,</span>
<span id="cb19-11">    replace<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="cb19-12">)</span>
<span id="cb19-13"></span>
<span id="cb19-14">plt.figure(figsize<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;">12</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb19-15"></span>
<span id="cb19-16">plt.hist(</span>
<span id="cb19-17">    source_population,</span>
<span id="cb19-18">    bins<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;">30</span>,</span>
<span id="cb19-19">    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.5</span>,</span>
<span id="cb19-20">    label<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;">"Source Population"</span></span>
<span id="cb19-21">)</span>
<span id="cb19-22"></span>
<span id="cb19-23">plt.hist(</span>
<span id="cb19-24">    founder_population,</span>
<span id="cb19-25">    bins<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;">30</span>,</span>
<span id="cb19-26">    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.5</span>,</span>
<span id="cb19-27">    label<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;">"Founder Population"</span></span>
<span id="cb19-28">)</span>
<span id="cb19-29"></span>
<span id="cb19-30">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allele Frequency"</span>)</span>
<span id="cb19-31">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Count"</span>)</span>
<span id="cb19-32"></span>
<span id="cb19-33">plt.title(</span>
<span id="cb19-34">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Founder Effect"</span></span>
<span id="cb19-35">)</span>
<span id="cb19-36"></span>
<span id="cb19-37">plt.legend()</span>
<span id="cb19-38"></span>
<span id="cb19-39">plt.show()</span>
<span id="cb19-40"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-19-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
</section>
<section id="interpretation-10" class="level3" data-number="0.54">
<h3 data-number="0.54" class="anchored" data-anchor-id="interpretation-10"><span class="header-section-number">0.54</span> Interpretation</h3>
<p>Even before evolution occurs, the founder population already differs genetically.</p>
<p>This is purely due to sampling.</p>
</section>
<section id="drift-across-an-entire-genome" class="level3" data-number="0.55">
<h3 data-number="0.55" class="anchored" data-anchor-id="drift-across-an-entire-genome"><span class="header-section-number">0.55</span> Drift Across an Entire Genome</h3>
<p>Now simulate:</p>
<ul>
<li>10,000 SNPs</li>
<li>500 generations</li>
</ul>
<div id="c1638d50-d73a-4d59-9b62-91611819c25a" class="cell" data-execution_count="19">
<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>
<span id="cb20-2">n_snps <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;">10000</span></span>
<span id="cb20-3"></span>
<span id="cb20-4">initial_freqs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.uniform(</span>
<span id="cb20-5">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.01</span>,</span>
<span id="cb20-6">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.99</span>,</span>
<span id="cb20-7">    n_snps</span>
<span id="cb20-8">)</span>
<span id="cb20-9"></span>
<span id="cb20-10">final_freqs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb20-11"></span>
<span id="cb20-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p0 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> initial_freqs:</span>
<span id="cb20-13"></span>
<span id="cb20-14">    traj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb20-15">        N<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;">100</span>,</span>
<span id="cb20-16">        p0<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p0,</span>
<span id="cb20-17">        generations<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-18">    )</span>
<span id="cb20-19"></span>
<span id="cb20-20">    final_freqs.append(</span>
<span id="cb20-21">        traj[<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-22">    )</span>
<span id="cb20-23"></span>
<span id="cb20-24"></span>
<span id="cb20-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Fate of Variants</span></span>
<span id="cb20-26"></span>
<span id="cb20-27"></span>
<span id="cb20-28">fixed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(</span>
<span id="cb20-29">    np.array(final_freqs)<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-30">)</span>
<span id="cb20-31"></span>
<span id="cb20-32">lost <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(</span>
<span id="cb20-33">    np.array(final_freqs)<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>
<span id="cb20-35"></span>
<span id="cb20-36">segregating <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb20-37">    n_snps<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>fixed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>lost</span>
<span id="cb20-38">)</span>
<span id="cb20-39"></span>
<span id="cb20-40"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fixed:"</span>, fixed)</span>
<span id="cb20-41"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lost:"</span>, lost)</span>
<span id="cb20-42"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Segregating:"</span>, segregating)</span>
<span id="cb20-43"></span>
<span id="cb20-44">plt.figure(figsize<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;">8</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb20-45"></span>
<span id="cb20-46">plt.bar(</span>
<span id="cb20-47">    [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lost"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fixed"</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Segregating"</span>],</span>
<span id="cb20-48">    [lost,fixed,segregating]</span>
<span id="cb20-49">)</span>
<span id="cb20-50"></span>
<span id="cb20-51">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of SNPs"</span>)</span>
<span id="cb20-52"></span>
<span id="cb20-53">plt.title(</span>
<span id="cb20-54">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genome-Wide Fate of Variants"</span></span>
<span id="cb20-55">)</span>
<span id="cb20-56"></span>
<span id="cb20-57">plt.show()</span>
<span id="cb20-58"></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Fixed: 4523
Lost: 4665
Segregating: 812</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-20-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-11" class="level3" data-number="0.56">
<h3 data-number="0.56" class="anchored" data-anchor-id="interpretation-11"><span class="header-section-number">0.56</span> Interpretation</h3>
<p>After sufficient evolutionary time:</p>
<ul>
<li>Many variants disappear</li>
<li>Many become fixed</li>
<li>Only a subset remain polymorphic</li>
</ul>
</section>
<section id="genetic-drift-and-population-structure" class="level3" data-number="0.57">
<h3 data-number="0.57" class="anchored" data-anchor-id="genetic-drift-and-population-structure"><span class="header-section-number">0.57</span> Genetic Drift and Population Structure</h3>
<p>Different populations experience different drift histories.</p>
<p>Suppose two populations split.</p>
<p>Each evolves independently.</p>
<p>Their allele frequencies diverge over time.</p>
</section>
<section id="simulating-divergence" class="level3" data-number="0.58">
<h3 data-number="0.58" class="anchored" data-anchor-id="simulating-divergence"><span class="header-section-number">0.58</span> Simulating Divergence</h3>
<div id="3f80abb5-d72e-4912-92e7-503b0f13509e" class="cell" data-execution_count="20">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"></span>
<span id="cb22-2">shared_freqs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.uniform(</span>
<span id="cb22-3">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>,</span>
<span id="cb22-4">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>,</span>
<span id="cb22-5">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span></span>
<span id="cb22-6">)</span>
<span id="cb22-7"></span>
<span id="cb22-8">population_A<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb22-9">population_B<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]</span>
<span id="cb22-10"></span>
<span id="cb22-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p0 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> shared_freqs:</span>
<span id="cb22-12"></span>
<span id="cb22-13">    trajA <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb22-14">        N<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;">100</span>,</span>
<span id="cb22-15">        p0<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p0,</span>
<span id="cb22-16">        generations<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;">100</span></span>
<span id="cb22-17">    )</span>
<span id="cb22-18"></span>
<span id="cb22-19">    trajB <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate_drift(</span>
<span id="cb22-20">        N<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;">100</span>,</span>
<span id="cb22-21">        p0<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p0,</span>
<span id="cb22-22">        generations<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;">100</span></span>
<span id="cb22-23">    )</span>
<span id="cb22-24"></span>
<span id="cb22-25">    population_A.append(</span>
<span id="cb22-26">        trajA[<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="cb22-27">    )</span>
<span id="cb22-28"></span>
<span id="cb22-29">    population_B.append(</span>
<span id="cb22-30">        trajB[<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="cb22-31">    )</span>
<span id="cb22-32"></span>
<span id="cb22-33">plt.figure(figsize<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;">8</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb22-34"></span>
<span id="cb22-35">plt.scatter(</span>
<span id="cb22-36">    population_A,</span>
<span id="cb22-37">    population_B,</span>
<span id="cb22-38">    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.5</span></span>
<span id="cb22-39">)</span>
<span id="cb22-40"></span>
<span id="cb22-41">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Population A"</span>)</span>
<span id="cb22-42">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Population B"</span>)</span>
<span id="cb22-43"></span>
<span id="cb22-44">plt.title(</span>
<span id="cb22-45">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Population Divergence Through Drift"</span></span>
<span id="cb22-46">)</span>
<span id="cb22-47"></span>
<span id="cb22-48">plt.show()</span>
<span id="cb22-49"></span>
<span id="cb22-50"></span>
<span id="cb22-51"></span>
<span id="cb22-52"></span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift_files/figure-html/cell-21-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="interpretation-12" class="level3" data-number="0.59">
<h3 data-number="0.59" class="anchored" data-anchor-id="interpretation-12"><span class="header-section-number">0.59</span> Interpretation</h3>
<p>The populations began identically.</p>
<p>Drift alone created differences.</p>
<p>This is the foundation of population structure.</p>
</section>
<section id="connection-to-fst" class="level3" data-number="0.60">
<h3 data-number="0.60" class="anchored" data-anchor-id="connection-to-fst"><span class="header-section-number">0.60</span> Connection to FST</h3>
<p>Population differentiation is often measured using:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AF_%7BST%7D%0A"></p>
<p>which quantifies how much allele frequencies differ between populations.</p>
<p>Drift increases:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AF_%7BST%7D%0A"></p>
<p>over time.</p>
</section>
<section id="why-gwas-researchers-care-about-drift" class="level3" data-number="0.61">
<h3 data-number="0.61" class="anchored" data-anchor-id="why-gwas-researchers-care-about-drift"><span class="header-section-number">0.61</span> Why GWAS Researchers Care About Drift</h3>
<p>Modern GWAS datasets contain individuals from populations with different demographic histories.</p>
<p>Drift can create allele-frequency differences unrelated to disease.</p>
<section id="example" class="level4" data-number="0.61.1">
<h4 data-number="0.61.1" class="anchored" data-anchor-id="example"><span class="header-section-number">0.61.1</span> Example</h4>
<p>Suppose:</p>
<p>Population A:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=0.7%0A"></p>
<p>Population B:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ap=0.3%0A"></p>
<p>for a SNP.</p>
<p>If disease prevalence also differs between populations, a naive GWAS may falsely associate the SNP with disease.</p>
</section>
<section id="confounding" class="level4" data-number="0.61.2">
<h4 data-number="0.61.2" class="anchored" data-anchor-id="confounding"><span class="header-section-number">0.61.2</span> Confounding</h4>
<p>This phenomenon is called:</p>
<p>Population stratification.</p>
<p>Drift is one of its major causes.</p>
</section>
</section>
<section id="how-gwas-controls-drift-effects" class="level3" data-number="0.62">
<h3 data-number="0.62" class="anchored" data-anchor-id="how-gwas-controls-drift-effects"><span class="header-section-number">0.62</span> How GWAS Controls Drift Effects</h3>
<p>Modern studies use:</p>
<ul>
<li>Principal Components Analysis (PCA)</li>
<li>Linear Mixed Models</li>
<li>Genetic Relationship Matrices</li>
<li>Ancestry Adjustment</li>
</ul>
<p>to account for population structure.</p>
</section>
<section id="connection-to-finngen" class="level3" data-number="0.63">
<h3 data-number="0.63" class="anchored" data-anchor-id="connection-to-finngen"><span class="header-section-number">0.63</span> Connection to FinnGen</h3>
<p>Finnish populations experienced:</p>
<ul>
<li>Founder events</li>
<li>Bottlenecks</li>
<li>Relative isolation</li>
</ul>
<p>Consequently:</p>
<ul>
<li>Some rare variants became common</li>
<li>Certain disease alleles increased in frequency</li>
</ul>
<p>This is known as the Finnish Disease Heritage.</p>
</section>
<section id="connection-to-uk-biobank" class="level3" data-number="0.64">
<h3 data-number="0.64" class="anchored" data-anchor-id="connection-to-uk-biobank"><span class="header-section-number">0.64</span> Connection to UK Biobank</h3>
<p>UK Biobank contains:</p>
<ul>
<li>Multiple ancestry groups</li>
<li>Geographic structure</li>
<li>Historical demographic differences</li>
</ul>
<p>These produce subtle allele-frequency differences caused partly by drift.</p>
</section>
<section id="connection-to-polygenic-scores" class="level3" data-number="0.65">
<h3 data-number="0.65" class="anchored" data-anchor-id="connection-to-polygenic-scores"><span class="header-section-number">0.65</span> Connection to Polygenic Scores</h3>
<p>Polygenic scores depend on allele frequencies.</p>
<p>Since drift changes frequencies:</p>
<ul>
<li>Prediction accuracy changes across populations</li>
<li>Transferability decreases</li>
<li>Ancestry matching becomes important</li>
</ul>
<ol type="1">
<li><p>Genetic drift is random evolution caused by finite populations.</p></li>
<li><p>Drift eventually causes fixation or extinction.</p></li>
<li><p>Small populations drift faster than large populations.</p></li>
<li><p>Heterozygosity decreases through time.</p></li>
<li><p>Effective population size determines drift strength.</p></li>
<li><p>Bottlenecks accelerate drift.</p></li>
<li><p>Founder effects reshape genetic variation.</p></li>
<li><p>Drift creates population structure.</p></li>
<li><p>Drift contributes to FST.</p></li>
<li><p>Drift influences GWAS, polygenic scores, and demographic inference.</p></li>
</ol>
</section>
<section id="summary-2" class="level3" data-number="0.66">
<h3 data-number="0.66" class="anchored" data-anchor-id="summary-2"><span class="header-section-number">0.66</span> Summary</h3>
<p>One of the most surprising lessons in population genetics is that evolution does not always require selection.</p>
<p>Randomness alone can dramatically reshape genomes.</p>
<p>Given enough time, drift can:</p>
<ul>
<li>Eliminate variants</li>
<li>Fix variants</li>
<li>Reduce diversity</li>
<li>Differentiate populations</li>
</ul>
<p>Many genomic patterns observed today arise not because some variants were better than others, but simply because finite populations are subject to chance.</p>
<p>Understanding genetic drift is therefore essential for evolutionary biology, statistical genetics, genomics, and modern precision medicine.</p>


</section>

 ]]></description>
  <category>Tutorial</category>
  <guid>https://bntechie.github.io/tutorials/genetic_drift/Genetic_Drift.html</guid>
  <pubDate>Mon, 01 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Colocalization Analysis in Statistical Genetics: Theory and Practical Example in R</title>
  <dc:creator>Nivedita Bhadra</dc:creator>
  <link>https://bntechie.github.io/tutorials/Colocalizatiom/Colocalization.html</link>
  <description><![CDATA[ 




<section id="introduction" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="introduction"><span class="header-section-number">1</span> Introduction</h2>
<p>Genome-wide association studies, or GWAS, have identified many genetic variants associated with complex traits and diseases. However, after identifying a GWAS locus, one important question remains:</p>
<blockquote class="blockquote">
<p>Which gene or biological mechanism is responsible for the association?</p>
</blockquote>
<p>Many GWAS variants are located in non-coding regions of the genome. They may not directly change protein sequence, but they may influence disease by changing gene regulation. This is where eQTL data becomes useful.</p>
<p>An eQTL is a genetic variant associated with gene expression. If a GWAS variant for a disease is also an eQTL for a nearby gene, it may suggest that the disease association works through altered gene expression.</p>
<p>However, this interpretation is not always safe.</p>
<p>The GWAS signal and the eQTL signal may appear to overlap simply because nearby SNPs are correlated through linkage disequilibrium, or LD. Therefore, visual overlap between GWAS and eQTL signals does not automatically mean that the same causal variant is responsible for both traits.</p>
<p>Colocalization analysis tries to answer this specific question:</p>
<blockquote class="blockquote">
<p>Are the GWAS and eQTL signals driven by the same causal variant?</p>
</blockquote>
</section>
<section id="why-colocalization-is-important" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="why-colocalization-is-important"><span class="header-section-number">2</span> Why Colocalization is Important</h2>
<p>Suppose a GWAS identifies a region associated with depression. In the same region, an eQTL study shows that a nearby SNP is associated with expression of Gene X.</p>
<p>A simple interpretation might be:</p>
<p>Gene X is involved in depression.</p>
<p>But this may be wrong.</p>
<p>There are at least two possible explanations.</p>
<p>First, the same causal variant may influence both Gene X expression and depression risk. This would support a shared biological mechanism.</p>
<p>Second, two different causal variants may exist in the same region. One variant may affect depression risk, while another nearby variant may affect Gene X expression. Because the variants are in LD, the signals may look similar even though they are biologically separate.</p>
<p>Colocalization is designed to distinguish between these two possibilities.</p>
</section>
<section id="relationship-between-gwas-eqtl-and-colocalization" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="relationship-between-gwas-eqtl-and-colocalization"><span class="header-section-number">3</span> Relationship Between GWAS, eQTL, and Colocalization</h2>
<p>GWAS asks:</p>
<p>Which variants are associated with disease or trait risk?</p>
<p>eQTL analysis asks:</p>
<p>Which variants are associated with gene expression?</p>
<p>Colocalization asks:</p>
<p>Are the GWAS and eQTL associations likely to share the same causal variant?</p>
<p>A simple post-GWAS workflow is:</p>
<pre class="text"><code>GWAS signal
    ↓
Check eQTL signal
    ↓
Run colocalization
    ↓
Prioritize candidate gene</code></pre>
<p>This is why colocalization is now widely used in post-GWAS interpretation, TWAS analysis, Mendelian Randomization, and drug target prioritization.</p>
</section>
<section id="the-five-colocalization-hypotheses" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="the-five-colocalization-hypotheses"><span class="header-section-number">4</span> The Five Colocalization Hypotheses</h2>
<p>The classical Bayesian colocalization framework evaluates five hypotheses.</p>
<section id="h0-no-association-with-either-trait" class="level3" data-number="4.1">
<h3 data-number="4.1" class="anchored" data-anchor-id="h0-no-association-with-either-trait"><span class="header-section-number">4.1</span> H0: No Association With Either Trait</h3>
<p>There is no evidence that variants in the region are associated with either trait.</p>
<pre class="text"><code>Trait 1: no association
Trait 2: no association</code></pre>
</section>
<section id="h1-association-with-trait-1-only" class="level3" data-number="4.2">
<h3 data-number="4.2" class="anchored" data-anchor-id="h1-association-with-trait-1-only"><span class="header-section-number">4.2</span> H1: Association With Trait 1 Only</h3>
<p>Only the first trait is associated in the region.</p>
<p>In many applications, trait 1 is the GWAS trait.</p>
<pre class="text"><code>GWAS trait: associated
eQTL trait: not associated</code></pre>
</section>
<section id="h2-association-with-trait-2-only" class="level3" data-number="4.3">
<h3 data-number="4.3" class="anchored" data-anchor-id="h2-association-with-trait-2-only"><span class="header-section-number">4.3</span> H2: Association With Trait 2 Only</h3>
<p>Only the second trait is associated in the region.</p>
<p>In many applications, trait 2 is gene expression.</p>
<pre class="text"><code>GWAS trait: not associated
eQTL trait: associated</code></pre>
</section>
<section id="h3-both-traits-associated-but-different-causal-variants" class="level3" data-number="4.4">
<h3 data-number="4.4" class="anchored" data-anchor-id="h3-both-traits-associated-but-different-causal-variants"><span class="header-section-number">4.4</span> H3: Both Traits Associated, But Different Causal Variants</h3>
<p>Both traits show association in the region, but the evidence suggests that they are driven by different causal variants.</p>
<pre class="text"><code>Variant A ──► Disease

Variant B ──► Gene Expression</code></pre>
<p>This means there is no strong evidence for a shared biological mechanism.</p>
</section>
<section id="h4-both-traits-associated-and-share-one-causal-variant" class="level3" data-number="4.5">
<h3 data-number="4.5" class="anchored" data-anchor-id="h4-both-traits-associated-and-share-one-causal-variant"><span class="header-section-number">4.5</span> H4: Both Traits Associated and Share One Causal Variant</h3>
<p>Both traits are associated, and the evidence suggests that the same causal variant drives both signals.</p>
<pre class="text"><code>Variant ──► Gene Expression
       └──► Disease Risk</code></pre>
<p>This is the main colocalization scenario researchers usually hope to find.</p>
</section>
</section>
<section id="the-most-important-quantity-pp.h4" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="the-most-important-quantity-pp.h4"><span class="header-section-number">5</span> The Most Important Quantity: PP.H4</h2>
<p>The coloc package reports posterior probabilities for each hypothesis.</p>
<p>The most important quantity is usually:</p>
<pre class="text"><code>PP.H4.abf</code></pre>
<p>This means the posterior probability that both traits share the same causal variant.</p>
<p>A rough interpretation is:</p>
<pre class="text"><code>PP.H4 &lt; 0.50       weak evidence for colocalization
PP.H4 0.50–0.80    moderate evidence
PP.H4 &gt; 0.80       strong evidence
PP.H4 &gt; 0.90       very strong evidence</code></pre>
<p>These are not universal rules. The threshold depends on the study design, sample size, prior assumptions, and biological context.</p>
<div id="6ba33c6e-098a-433a-be7c-98ca8740f442" class="cell" data-execution_count="1">
<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>
<span id="cb9-2"></span>
<span id="cb9-3"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Install and Load Required Packages</span></span>
<span id="cb9-4"></span>
<span id="cb9-5"></span>
<span id="cb9-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Install packages if needed</span></span>
<span id="cb9-7"> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#install.packages("coloc")</span></span>
<span id="cb9-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("ggplot2")</span></span>
<span id="cb9-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("dplyr")</span></span>
<span id="cb9-10"></span>
<span id="cb9-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(coloc)</span>
<span id="cb9-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb9-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span></code></pre></div></div>
</div>
</section>
<section id="simulated-example-using-the-coloc-package" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="simulated-example-using-the-coloc-package"><span class="header-section-number">6</span> Simulated Example Using the coloc Package</h2>
<p>In this example, we simulate 100 SNPs from one genomic region. We create one GWAS signal and one eQTL signal. Both are given a strong effect at SNP 50, representing a simplified shared causal variant.</p>
<p>This is a toy example, but it helps us understand what the <code>coloc.abf()</code> function needs as input.</p>
<div id="1e7c5450-5c1e-4122-a1eb-e0dd4f1a16e7" class="cell" data-execution_count="2">
<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;">42</span>)</span>
<span id="cb10-2"></span>
<span id="cb10-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of SNPs in the region</span></span>
<span id="cb10-4">n_snps <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="cb10-5"></span>
<span id="cb10-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># SNP IDs and positions</span></span>
<span id="cb10-7">snp_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;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs"</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_snps)</span>
<span id="cb10-8">position <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>n_snps</span>
<span id="cb10-9"></span>
<span id="cb10-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Minor allele frequencies</span></span>
<span id="cb10-11">maf <span class="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>(n_snps, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">min =</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;">max =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.50</span>)</span>
<span id="cb10-12"></span>
<span id="cb10-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Standard errors</span></span>
<span id="cb10-14">gwas_se <span class="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="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, n_snps)</span>
<span id="cb10-15">eqtl_se <span class="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="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, n_snps)</span>
<span id="cb10-16"></span>
<span id="cb10-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simulate small background effects</span></span>
<span id="cb10-18">gwas_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;">rnorm</span>(n_snps, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</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;">sd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb10-19">eqtl_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;">rnorm</span>(n_snps, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</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;">sd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb10-20"></span>
<span id="cb10-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add one shared causal signal at SNP 50</span></span>
<span id="cb10-22">gwas_beta[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>] <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.50</span></span>
<span id="cb10-23">eqtl_beta[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>] <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.60</span></span>
<span id="cb10-24"></span>
<span id="cb10-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create a data frame for visualization</span></span>
<span id="cb10-26">sim_data <span class="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-27">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">SNP =</span> snp_ids,</span>
<span id="cb10-28">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Position =</span> position,</span>
<span id="cb10-29">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MAF =</span> maf,</span>
<span id="cb10-30">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">GWAS_Beta =</span> gwas_beta,</span>
<span id="cb10-31">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eQTL_Beta =</span> eqtl_beta,</span>
<span id="cb10-32">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">GWAS_SE =</span> gwas_se,</span>
<span id="cb10-33">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eQTL_SE =</span> eqtl_se</span>
<span id="cb10-34">)</span>
<span id="cb10-35"></span>
<span id="cb10-36"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(sim_data)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 6 × 7</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">SNP</th>
<th data-quarto-table-cell-role="th" scope="col">Position</th>
<th data-quarto-table-cell-role="th" scope="col">MAF</th>
<th data-quarto-table-cell-role="th" scope="col">GWAS_Beta</th>
<th data-quarto-table-cell-role="th" scope="col">eQTL_Beta</th>
<th data-quarto-table-cell-role="th" scope="col">GWAS_SE</th>
<th data-quarto-table-cell-role="th" scope="col">eQTL_SE</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th" scope="col">&lt;chr&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;int&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">1</th>
<td>rs1</td>
<td>1</td>
<td>0.4616627</td>
<td>0.016096263</td>
<td>-0.002034924</td>
<td>0.05</td>
<td>0.05</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">2</th>
<td>rs2</td>
<td>2</td>
<td>0.4716839</td>
<td>-0.039191947</td>
<td>-0.077577241</td>
<td>0.05</td>
<td>0.05</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">3</th>
<td>rs3</td>
<td>3</td>
<td>0.1787628</td>
<td>0.078786376</td>
<td>0.058358477</td>
<td>0.05</td>
<td>0.05</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">4</th>
<td>rs4</td>
<td>4</td>
<td>0.4237014</td>
<td>0.032144965</td>
<td>-0.013682285</td>
<td>0.05</td>
<td>0.05</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th" scope="row">5</th>
<td>rs5</td>
<td>5</td>
<td>0.3387855</td>
<td>0.004488032</td>
<td>-0.023392266</td>
<td>0.05</td>
<td>0.05</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="row">6</th>
<td>rs6</td>
<td>6</td>
<td>0.2835932</td>
<td>0.013827537</td>
<td>-0.061912616</td>
<td>0.05</td>
<td>0.05</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="67cbb944-4606-4df3-9acc-62dc6b0b10b2" class="cell" data-execution_count="3">
<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"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Visualize the Simulated Signals</span></span>
<span id="cb11-2"></span>
<span id="cb11-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(sim_data, <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> Position)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-4">  <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;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(GWAS_Beta), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GWAS"</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="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="cb11-5">  <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;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(eQTL_Beta), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"eQTL"</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="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="cb11-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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</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="cb11-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb11-8">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Simulated GWAS and eQTL Signals"</span>,</span>
<span id="cb11-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">subtitle =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Both traits have a strong signal at SNP 50"</span>,</span>
<span id="cb11-10">    <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;">"SNP Position"</span>,</span>
<span id="cb11-11">    <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;">"Absolute Effect Size"</span>,</span>
<span id="cb11-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dataset"</span></span>
<span id="cb11-13">  ) <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_minimal</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/Colocalizatiom/Colocalization_files/figure-html/cell-4-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="prepare-data-for-coloc" class="level2" data-number="7">
<h2 data-number="7" class="anchored" data-anchor-id="prepare-data-for-coloc"><span class="header-section-number">7</span> Prepare Data for coloc</h2>
<p>The <code>coloc.abf()</code> function needs the GWAS and eQTL data as lists.</p>
<p>For the GWAS dataset, we use:</p>
<pre class="text"><code>type = "cc"</code></pre>
<p>because the GWAS trait is treated as a case-control disease outcome.</p>
<p>For the eQTL dataset, we use:</p>
<pre class="text"><code>type = "quant"</code></pre>
<p>because gene expression is a quantitative trait.</p>
<p>For quantitative traits, <code>coloc</code> needs either <code>sdY</code>, or enough information to estimate it. Here we set:</p>
<pre class="text"><code>sdY = 1</code></pre>
<p>because this is a simulated example.</p>
<div id="77bfbf90-c11d-4cb1-85b0-9c0f13955b47" class="cell" data-execution_count="4">
<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">gwas_data <span class="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="cb15-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">beta =</span> gwas_beta,</span>
<span id="cb15-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">varbeta =</span> gwas_se<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="cb15-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">snp =</span> snp_ids,</span>
<span id="cb15-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MAF =</span> maf,</span>
<span id="cb15-6">  <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;">"cc"</span>,</span>
<span id="cb15-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.30</span>,</span>
<span id="cb15-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">N =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50000</span></span>
<span id="cb15-9">)</span>
<span id="cb15-10"></span>
<span id="cb15-11">eqtl_data <span class="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="cb15-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">beta =</span> eqtl_beta,</span>
<span id="cb15-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">varbeta =</span> eqtl_se<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="cb15-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">snp =</span> snp_ids,</span>
<span id="cb15-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MAF =</span> maf,</span>
<span id="cb15-16">  <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;">"quant"</span>,</span>
<span id="cb15-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">N =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>,</span>
<span id="cb15-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sdY =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb15-19">)</span></code></pre></div></div>
</div>
<div id="881bfb17-e29b-4d45-b182-eda0bea36889" class="cell" data-execution_count="5">
<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>
<span id="cb16-2"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Run Colocalization Analysis</span></span>
<span id="cb16-3"></span>
<span id="cb16-4">coloc_result <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coloc.abf</span>(</span>
<span id="cb16-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dataset1 =</span> gwas_data,</span>
<span id="cb16-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dataset2 =</span> eqtl_data</span>
<span id="cb16-7">)</span>
<span id="cb16-8"></span>
<span id="cb16-9">coloc_result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>summary</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>PP.H0.abf PP.H1.abf PP.H2.abf PP.H3.abf PP.H4.abf 
 3.43e-43  2.28e-27  1.51e-19  0.00e+00  1.00e+00 
[1] "PP abf for shared variant: 100%"</code></pre>
</div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>nsnps</dt><dd>100</dd><dt>PP.H0.abf</dt><dd>3.43205824565904e-43</dd><dt>PP.H1.abf</dt><dd>2.27885961807598e-27</dd><dt>PP.H2.abf</dt><dd>1.50604197750307e-19</dd><dt>PP.H3.abf</dt><dd>0</dd><dt>PP.H4.abf</dt><dd>1</dd></dl>
</div>
</div>
</section>
<section id="examine-results" class="level2" data-number="8">
<h2 data-number="8" class="anchored" data-anchor-id="examine-results"><span class="header-section-number">8</span> Examine Results</h2>
<p>The output contains posterior probabilities for the five hypotheses considered by the coloc model.</p>
<pre class="text"><code>H0: Neither trait is associated in the region
H1: Only trait 1 is associated
H2: Only trait 2 is associated
H3: Both traits are associated, but with different causal variants
H4: Both traits are associated and share the same causal variant</code></pre>
<p>The most important quantity is:</p>
<pre class="text"><code>PP.H4.abf</code></pre>
<p>This tells us the posterior probability that the GWAS and eQTL signals are driven by the same causal variant.</p>
<p>For example, if the output shows:</p>
<pre class="text"><code>PP.H4.abf = 0.90</code></pre>
<p>we would interpret this as strong evidence that the GWAS and eQTL signals colocalize.</p>
<div id="68a8991f-d7a9-4c84-9e87-c10198e54164" class="cell" data-execution_count="6">
<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="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Extract the Posterior Probabilities</span></span>
<span id="cb21-2"></span>
<span id="cb21-3"></span>
<span id="cb21-4">posterior_probs <span class="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;">t</span>(coloc_result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>summary))</span>
<span id="cb21-5"></span>
<span id="cb21-6">posterior_probs</span>
<span id="cb21-7"></span>
<span id="cb21-8"></span>
<span id="cb21-9"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Visualize Posterior Probabilities</span></span>
<span id="cb21-10"></span>
<span id="cb21-11"></span>
<span id="cb21-12">posterior_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="cb21-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Hypothesis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(coloc_result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>summary),</span>
<span id="cb21-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Posterior_Probability =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(coloc_result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>summary)</span>
<span id="cb21-15">)</span>
<span id="cb21-16"></span>
<span id="cb21-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(posterior_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;">x =</span> Hypothesis, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Posterior_Probability)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb21-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_col</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb21-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb21-20">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Posterior Probabilities from Colocalization Analysis"</span>,</span>
<span id="cb21-21">    <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;">"Hypothesis"</span>,</span>
<span id="cb21-22">    <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;">"Posterior Probability"</span></span>
<span id="cb21-23">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb21-24">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small">
<caption>A data.frame: 1 × 6</caption>
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th" scope="col">nsnps</th>
<th data-quarto-table-cell-role="th" scope="col">PP.H0.abf</th>
<th data-quarto-table-cell-role="th" scope="col">PP.H1.abf</th>
<th data-quarto-table-cell-role="th" scope="col">PP.H2.abf</th>
<th data-quarto-table-cell-role="th" scope="col">PP.H3.abf</th>
<th data-quarto-table-cell-role="th" scope="col">PP.H4.abf</th>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
<th data-quarto-table-cell-role="th" scope="col">&lt;dbl&gt;</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>100</td>
<td>3.432058e-43</td>
<td>2.27886e-27</td>
<td>1.506042e-19</td>
<td>0</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/Colocalizatiom/Colocalization_files/figure-html/cell-7-output-2.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="understanding-h3-vs-h4" class="level2" data-number="9">
<h2 data-number="9" class="anchored" data-anchor-id="understanding-h3-vs-h4"><span class="header-section-number">9</span> Understanding H3 vs H4</h2>
<p>The distinction between H3 and H4 is one of the most important concepts in colocalization analysis.</p>
<p>A common misconception is that overlapping GWAS and eQTL association peaks automatically imply that the same variant is responsible for both signals. Because nearby variants are often correlated through LD, this assumption can be incorrect.</p>
<section id="h3-different-causal-variants" class="level3" data-number="9.1">
<h3 data-number="9.1" class="anchored" data-anchor-id="h3-different-causal-variants"><span class="header-section-number">9.1</span> H3: Different Causal Variants</h3>
<p>A high posterior probability for H3 means that both traits are associated in the region, but they are probably driven by different causal variants.</p>
<p>Conceptually:</p>
<pre class="text"><code>Variant A ──► Disease

Variant B ──► Gene Expression</code></pre>
<p>In this case, the region contains both a GWAS signal and an eQTL signal, but there is little evidence that the gene expression change explains the disease association.</p>
</section>
<section id="h4-shared-causal-variant" class="level3" data-number="9.2">
<h3 data-number="9.2" class="anchored" data-anchor-id="h4-shared-causal-variant"><span class="header-section-number">9.2</span> H4: Shared Causal Variant</h3>
<p>A high posterior probability for H4 means that the same variant is likely responsible for both the GWAS and eQTL associations.</p>
<p>Conceptually:</p>
<pre class="text"><code>Variant
    │
    ├──► Gene Expression
    │
    └──► Disease Risk</code></pre>
<p>This is often interpreted as evidence that altered gene expression may be involved in disease biology.</p>
</section>
</section>
<section id="simulating-a-different-causal-variant-scenario" class="level2" data-number="10">
<h2 data-number="10" class="anchored" data-anchor-id="simulating-a-different-causal-variant-scenario"><span class="header-section-number">10</span> Simulating a Different-Causal-Variant Scenario</h2>
<p>Now we simulate a second example where the GWAS signal is strongest at SNP 40 and the eQTL signal is strongest at SNP 70.</p>
<p>This represents a situation where both traits are associated in the region, but likely through different causal variants.</p>
<div id="28584889-9aa4-4f65-a533-adf49d729af8" class="cell" data-execution_count="7">
<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;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">123</span>)</span>
<span id="cb24-2"></span>
<span id="cb24-3">gwas_beta_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;">rnorm</span>(n_snps, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</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;">sd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb24-4">eqtl_beta_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;">rnorm</span>(n_snps, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</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;">sd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb24-5"></span>
<span id="cb24-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Different causal SNPs</span></span>
<span id="cb24-7">gwas_beta_diff[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>] <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.50</span></span>
<span id="cb24-8">eqtl_beta_diff[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">70</span>] <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.60</span></span>
<span id="cb24-9"></span>
<span id="cb24-10">diff_data <span class="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="cb24-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">SNP =</span> snp_ids,</span>
<span id="cb24-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Position =</span> position,</span>
<span id="cb24-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">GWAS_Beta =</span> gwas_beta_diff,</span>
<span id="cb24-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eQTL_Beta =</span> eqtl_beta_diff</span>
<span id="cb24-15">)</span>
<span id="cb24-16"></span>
<span id="cb24-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(diff_data, <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> Position)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-18">  <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;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(GWAS_Beta), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GWAS"</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="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="cb24-19">  <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;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(eQTL_Beta), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"eQTL"</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="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="cb24-20">  <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;">40</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="cb24-21">  <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;">70</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;">"dotted"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb24-23">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Different Causal Variant Scenario"</span>,</span>
<span id="cb24-24">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">subtitle =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GWAS peak and eQTL peak occur at different SNPs"</span>,</span>
<span id="cb24-25">    <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;">"SNP Position"</span>,</span>
<span id="cb24-26">    <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;">"Absolute Effect Size"</span>,</span>
<span id="cb24-27">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dataset"</span></span>
<span id="cb24-28">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-29">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://bntechie.github.io/tutorials/Colocalizatiom/Colocalization_files/figure-html/cell-8-output-1.png" width="420" height="420" class="figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="a394d420-eb4b-4479-a0b8-a1c45a23ec9d" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb25-1">gwas_data_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;">list</span>(</span>
<span id="cb25-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">beta =</span> gwas_beta_diff,</span>
<span id="cb25-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">varbeta =</span> gwas_se<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="cb25-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">snp =</span> snp_ids,</span>
<span id="cb25-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MAF =</span> maf,</span>
<span id="cb25-6">  <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;">"cc"</span>,</span>
<span id="cb25-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.30</span>,</span>
<span id="cb25-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">N =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50000</span></span>
<span id="cb25-9">)</span>
<span id="cb25-10"></span>
<span id="cb25-11">eqtl_data_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;">list</span>(</span>
<span id="cb25-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">beta =</span> eqtl_beta_diff,</span>
<span id="cb25-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">varbeta =</span> eqtl_se<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="cb25-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">snp =</span> snp_ids,</span>
<span id="cb25-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MAF =</span> maf,</span>
<span id="cb25-16">  <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;">"quant"</span>,</span>
<span id="cb25-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">N =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>,</span>
<span id="cb25-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sdY =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb25-19">)</span>
<span id="cb25-20"></span>
<span id="cb25-21">coloc_result_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;">coloc.abf</span>(</span>
<span id="cb25-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dataset1 =</span> gwas_data_diff,</span>
<span id="cb25-23">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dataset2 =</span> eqtl_data_diff</span>
<span id="cb25-24">)</span>
<span id="cb25-25"></span>
<span id="cb25-26">coloc_result_diff<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>summary</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>PP.H0.abf PP.H1.abf PP.H2.abf PP.H3.abf PP.H4.abf 
 3.43e-40  2.28e-24  1.51e-16  1.00e+00  2.64e-17 
[1] "PP abf for shared variant: 2.64e-15%"</code></pre>
</div>
<div class="cell-output cell-output-display">
<style>
.dl-inline {width: auto; margin:0; padding: 0}
.dl-inline>dt, .dl-inline>dd {float: none; width: auto; display: inline-block}
.dl-inline>dt::after {content: ":\0020"; padding-right: .5ex}
.dl-inline>dt:not(:first-of-type) {padding-left: .5ex}
</style><dl class="dl-inline"><dt>nsnps</dt><dd>100</dd><dt>PP.H0.abf</dt><dd>3.43205824565904e-40</dd><dt>PP.H1.abf</dt><dd>2.27885961807598e-24</dd><dt>PP.H2.abf</dt><dd>1.50604197750307e-16</dd><dt>PP.H3.abf</dt><dd>1</dd><dt>PP.H4.abf</dt><dd>2.63976208317766e-17</dd></dl>
</div>
</div>
<p>In this second example, we expect less support for H4 compared with the shared-causal-variant example. Depending on the simulated values and priors, H3 may become more prominent because both traits have signals but not at the same SNP.</p>
</section>
<section id="why-visual-overlap-is-not-enough" class="level2" data-number="11">
<h2 data-number="11" class="anchored" data-anchor-id="why-visual-overlap-is-not-enough"><span class="header-section-number">11</span> Why Visual Overlap Is Not Enough</h2>
<p>It is tempting to look at two regional plots and decide whether the peaks overlap. However, nearby SNPs are often correlated because of LD.</p>
<p>This means two different causal variants can produce similar association patterns.</p>
<p>Therefore, colocalization is stronger than visual inspection because it formally compares hypotheses about shared and distinct causal variants.</p>
</section>
<section id="colocalization-and-twas" class="level2" data-number="12">
<h2 data-number="12" class="anchored" data-anchor-id="colocalization-and-twas"><span class="header-section-number">12</span> Colocalization and TWAS</h2>
<p>Transcriptome-wide association studies, or TWAS, test whether genetically predicted gene expression is associated with a trait.</p>
<p>A simplified TWAS idea is:</p>
<pre class="text"><code>Genetic variants ──► Predicted gene expression ──► Disease trait</code></pre>
<p>However, TWAS signals can arise because of LD or multiple nearby genes with correlated expression. Therefore, a significant TWAS result does not automatically prove that the gene is causal.</p>
<p>Colocalization is often used alongside TWAS.</p>
<p>A stronger interpretation is possible when:</p>
<pre class="text"><code>Gene is significant in TWAS
+
GWAS and eQTL signals colocalize</code></pre>
<p>This combination gives more confidence that the gene may be biologically relevant.</p>
</section>
<section id="colocalization-and-mendelian-randomization" class="level2" data-number="13">
<h2 data-number="13" class="anchored" data-anchor-id="colocalization-and-mendelian-randomization"><span class="header-section-number">13</span> Colocalization and Mendelian Randomization</h2>
<p>Mendelian Randomization, or MR, can be used to test whether genetically predicted exposure affects an outcome.</p>
<p>For gene expression studies, the exposure may be expression of a gene and the outcome may be disease risk.</p>
<p>MR asks:</p>
<p>Does gene expression causally affect disease?</p>
<p>Colocalization asks:</p>
<p>Do gene expression and disease share the same causal variant?</p>
<p>These are related but different questions.</p>
<p>If MR suggests a causal effect but colocalization is weak, the MR result may be driven by LD or pleiotropy. Therefore, colocalization is often an important sensitivity analysis for expression-based MR.</p>
</section>
<section id="limitations-of-classical-colocalization" class="level2" data-number="14">
<h2 data-number="14" class="anchored" data-anchor-id="limitations-of-classical-colocalization"><span class="header-section-number">14</span> Limitations of Classical Colocalization</h2>
<p>The classical coloc method assumes one causal variant per region for each trait. This assumption may not always hold.</p>
<p>Real genetic loci can contain multiple independent signals.</p>
<p>Other limitations include:</p>
<pre class="text"><code>Incorrect LD structure
Poor variant coverage
Allele harmonization errors
Different ancestry between datasets
Weak eQTL sample size
Tissue mismatch
Multiple causal variants</code></pre>
<p>Because of these limitations, colocalization should not be interpreted mechanically. A high PP.H4 is useful evidence, but it should be considered together with biology, tissue relevance, fine-mapping, and replication.</p>
</section>
<section id="modern-extensions" class="level2" data-number="15">
<h2 data-number="15" class="anchored" data-anchor-id="modern-extensions"><span class="header-section-number">15</span> Modern Extensions</h2>
<p>Several newer methods extend classical colocalization.</p>
<section id="susie-coloc" class="level3" data-number="15.1">
<h3 data-number="15.1" class="anchored" data-anchor-id="susie-coloc"><span class="header-section-number">15.1</span> SuSiE-Coloc</h3>
<p>SuSiE-coloc combines colocalization with fine-mapping and can handle multiple causal signals in a region.</p>
</section>
<section id="ecaviar" class="level3" data-number="15.2">
<h3 data-number="15.2" class="anchored" data-anchor-id="ecaviar"><span class="header-section-number">15.2</span> eCAVIAR</h3>
<p>eCAVIAR jointly models colocalization and fine-mapping while accounting for LD.</p>
</section>
<section id="fastenloc" class="level3" data-number="15.3">
<h3 data-number="15.3" class="anchored" data-anchor-id="fastenloc"><span class="header-section-number">15.3</span> fastENLOC</h3>
<p>fastENLOC is designed for large-scale enrichment and colocalization analyses across many loci and molecular traits.</p>
<p>These methods are useful when the simple one-causal-variant assumption is unrealistic.</p>
</section>
</section>
<section id="practical-interpretation-checklist" class="level2" data-number="16">
<h2 data-number="16" class="anchored" data-anchor-id="practical-interpretation-checklist"><span class="header-section-number">16</span> Practical Interpretation Checklist</h2>
<p>When interpreting colocalization results, I would check the following:</p>
<pre class="text"><code>1. Is there a strong GWAS signal in the region?
2. Is there a strong eQTL signal in the same tissue?
3. Are the alleles harmonized correctly?
4. Are the GWAS and eQTL datasets ancestry-matched?
5. Is PP.H4 high?
6. Is PP.H3 also high?
7. Is the tissue biologically relevant?
8. Does the result agree with TWAS, MR, or functional evidence?</code></pre>
<p>A high PP.H4 is helpful, but it is not the final proof of causality.</p>
</section>
<section id="summary" class="level2" data-number="17">
<h2 data-number="17" class="anchored" data-anchor-id="summary"><span class="header-section-number">17</span> Summary</h2>
<p>Colocalization analysis is a key method in post-GWAS interpretation. It helps determine whether two association signals, such as a disease GWAS signal and an eQTL signal, are likely to share the same causal variant.</p>
<p>The main idea is simple but important:</p>
<pre class="text"><code>Overlapping association signals do not automatically mean shared causality.</code></pre>
<p>The coloc framework evaluates five hypotheses: H0, H1, H2, H3, and H4. Among these, H4 is usually the most important because it represents evidence that both traits share one causal variant.</p>
<p>In practical genetic studies, colocalization is often used together with eQTL analysis, TWAS, MR, and fine-mapping to prioritize genes and biological mechanisms.</p>
<p>For researchers working with GWAS, FinnGen, UK Biobank, GTEx, PsychENCODE, or other molecular QTL resources, colocalization is one of the most useful tools for moving from statistical association toward biological interpretation.</p>
</section>
<section id="references" class="level2" data-number="18">
<h2 data-number="18" class="anchored" data-anchor-id="references"><span class="header-section-number">18</span> References</h2>
<p>Giambartolomei, C. et al.&nbsp;Bayesian test for colocalisation between pairs of genetic association studies using summary statistics. PLoS Genetics, 2014.</p>
<p>Wallace, C. A more accurate method for colocalisation analysis allowing for multiple causal variants. PLoS Genetics, 2021.</p>
<p>GTEx Consortium. The GTEx Consortium atlas of genetic regulatory effects across human tissues. Science, 2020.</p>
<p>Hormozdiari, F. et al.&nbsp;Colocalization of GWAS and eQTL signals detects target genes. American Journal of Human Genetics, 2016.</p>


</section>

 ]]></description>
  <category>Statistical Genetics</category>
  <category>GWAS</category>
  <category>eQTL</category>
  <category>Colocalization</category>
  <category>TWAS</category>
  <category>Mendelian Randomization</category>
  <guid>https://bntechie.github.io/tutorials/Colocalizatiom/Colocalization.html</guid>
  <pubDate>Thu, 28 May 2026 21:00:00 GMT</pubDate>
</item>
</channel>
</rss>
