<?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>Rverse Analytics Blog</title>
<link>https://rverseanalytics.com/blog.html</link>
<atom:link href="https://rverseanalytics.com/blog.xml" rel="self" type="application/rss+xml"/>
<description>Notes on R, statistics and reproducible workflows.</description>
<image>
<url>https://rverseanalytics.com/assets/og-image.png</url>
<title>Rverse Analytics Blog</title>
<link>https://rverseanalytics.com/blog.html</link>
<height>76</height>
<width>144</width>
</image>
<generator>quarto-1.9.38</generator>
<lastBuildDate>Wed, 08 Jul 2026 21:00:00 GMT</lastBuildDate>
<item>
  <title>Your Table 1, in one line, with gtsummary</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/table1-baseline-characteristics-gtsummary.html</link>
  <description><![CDATA[ 




<p>Every clinical paper opens with the same table: participant characteristics, split by group. Built by hand it is tedious and easy to get wrong — the wrong summary statistic, the wrong test, a percentage that doesn’t add up. <code>gtsummary</code> builds it correctly from one function call, and regenerates it the moment your data changes.</p>
<section id="the-one-liner" class="level2">
<h2 class="anchored" data-anchor-id="the-one-liner">The one-liner</h2>
<p>We’ll use the <code>trial</code> dataset that ships with <code>gtsummary</code> — a small clinical-trial example:</p>
<div class="cell">
<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;">library</span>(gtsummary)</span>
<span id="cb1-2"></span>
<span id="cb1-3">trial <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb1-4">  dplyr<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;">select</span>(trt, age, grade, marker, stage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb1-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tbl_summary</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> trt) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb1-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_p</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div id="keixsodgzr" style="padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
<style>#keixsodgzr table {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#keixsodgzr thead, #keixsodgzr tbody, #keixsodgzr tfoot, #keixsodgzr tr, #keixsodgzr td, #keixsodgzr th {
  border-style: none;
}

#keixsodgzr p {
  margin: 0;
  padding: 0;
}

#keixsodgzr .gt_table {
  display: table;
  border-collapse: collapse;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 16px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
}

#keixsodgzr .gt_caption {
  padding-top: 4px;
  padding-bottom: 4px;
}

#keixsodgzr .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}

#keixsodgzr .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}

#keixsodgzr .gt_heading {
  background-color: #FFFFFF;
  text-align: center;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#keixsodgzr .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#keixsodgzr .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#keixsodgzr .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 6px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}

#keixsodgzr .gt_column_spanner_outer {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 4px;
  padding-right: 4px;
}

#keixsodgzr .gt_column_spanner_outer:first-child {
  padding-left: 0;
}

#keixsodgzr .gt_column_spanner_outer:last-child {
  padding-right: 0;
}

#keixsodgzr .gt_column_spanner {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  overflow-x: hidden;
  display: inline-block;
  width: 100%;
}

#keixsodgzr .gt_spanner_row {
  border-bottom-style: hidden;
}

#keixsodgzr .gt_group_heading {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  text-align: left;
}

#keixsodgzr .gt_empty_group_heading {
  padding: 0.5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: middle;
}

#keixsodgzr .gt_from_md > :first-child {
  margin-top: 0;
}

#keixsodgzr .gt_from_md > :last-child {
  margin-bottom: 0;
}

#keixsodgzr .gt_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  overflow-x: hidden;
}

#keixsodgzr .gt_stub {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
}

#keixsodgzr .gt_stub_row_group {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
  vertical-align: top;
}

#keixsodgzr .gt_row_group_first td {
  border-top-width: 2px;
}

#keixsodgzr .gt_row_group_first th {
  border-top-width: 2px;
}

#keixsodgzr .gt_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#keixsodgzr .gt_first_summary_row {
  border-top-style: solid;
  border-top-color: #D3D3D3;
}

#keixsodgzr .gt_first_summary_row.thick {
  border-top-width: 2px;
}

#keixsodgzr .gt_last_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#keixsodgzr .gt_grand_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#keixsodgzr .gt_first_grand_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-style: double;
  border-top-width: 6px;
  border-top-color: #D3D3D3;
}

#keixsodgzr .gt_last_grand_summary_row_top {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: double;
  border-bottom-width: 6px;
  border-bottom-color: #D3D3D3;
}

#keixsodgzr .gt_striped {
  background-color: rgba(128, 128, 128, 0.05);
}

#keixsodgzr .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#keixsodgzr .gt_footnotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#keixsodgzr .gt_footnote {
  margin: 0px;
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#keixsodgzr .gt_sourcenotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#keixsodgzr .gt_sourcenote {
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#keixsodgzr .gt_left {
  text-align: left;
}

#keixsodgzr .gt_center {
  text-align: center;
}

#keixsodgzr .gt_right {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#keixsodgzr .gt_font_normal {
  font-weight: normal;
}

#keixsodgzr .gt_font_bold {
  font-weight: bold;
}

#keixsodgzr .gt_font_italic {
  font-style: italic;
}

#keixsodgzr .gt_super {
  font-size: 65%;
}

#keixsodgzr .gt_footnote_marks {
  font-size: 75%;
  vertical-align: 0.4em;
  position: initial;
}

#keixsodgzr .gt_asterisk {
  font-size: 100%;
  vertical-align: 0;
}

#keixsodgzr .gt_indent_1 {
  text-indent: 5px;
}

#keixsodgzr .gt_indent_2 {
  text-indent: 10px;
}

#keixsodgzr .gt_indent_3 {
  text-indent: 15px;
}

#keixsodgzr .gt_indent_4 {
  text-indent: 20px;
}

#keixsodgzr .gt_indent_5 {
  text-indent: 25px;
}

#keixsodgzr .katex-display {
  display: inline-flex !important;
  margin-bottom: 0.75em !important;
}

#keixsodgzr div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {
  height: 0px !important;
}
</style>

<table class="gt_table caption-top table table-sm table-striped small" data-quarto-bootstrap="false">
<colgroup>
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
</colgroup>
<thead>
<tr class="gt_col_headings header">
<th id="label" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col"><strong>Characteristic</strong></th>
<th id="stat_1" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>Drug A</strong><br>
N = 98<span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>1</sup></span></th>
<th id="stat_2" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>Drug B</strong><br>
N = 102<span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>1</sup></span></th>
<th id="p.value" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>p-value</strong><span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>2</sup></span></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr class="odd">
<td class="gt_row gt_left" headers="label">Age</td>
<td class="gt_row gt_center" headers="stat_1">46 (37, 60)</td>
<td class="gt_row gt_center" headers="stat_2">48 (39, 56)</td>
<td class="gt_row gt_center" headers="p.value">0.7</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;Unknown</td>
<td class="gt_row gt_center" headers="stat_1">7</td>
<td class="gt_row gt_center" headers="stat_2">4</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">Grade</td>
<td class="gt_row gt_center" headers="stat_1"><br>
</td>
<td class="gt_row gt_center" headers="stat_2"><br>
</td>
<td class="gt_row gt_center" headers="p.value">0.9</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;I</td>
<td class="gt_row gt_center" headers="stat_1">35 (36%)</td>
<td class="gt_row gt_center" headers="stat_2">33 (32%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;II</td>
<td class="gt_row gt_center" headers="stat_1">32 (33%)</td>
<td class="gt_row gt_center" headers="stat_2">36 (35%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;III</td>
<td class="gt_row gt_center" headers="stat_1">31 (32%)</td>
<td class="gt_row gt_center" headers="stat_2">33 (32%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">Marker Level (ng/mL)</td>
<td class="gt_row gt_center" headers="stat_1">0.84 (0.23, 1.60)</td>
<td class="gt_row gt_center" headers="stat_2">0.52 (0.18, 1.21)</td>
<td class="gt_row gt_center" headers="p.value">0.085</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;Unknown</td>
<td class="gt_row gt_center" headers="stat_1">6</td>
<td class="gt_row gt_center" headers="stat_2">4</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">T Stage</td>
<td class="gt_row gt_center" headers="stat_1"><br>
</td>
<td class="gt_row gt_center" headers="stat_2"><br>
</td>
<td class="gt_row gt_center" headers="p.value">0.9</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;T1</td>
<td class="gt_row gt_center" headers="stat_1">28 (29%)</td>
<td class="gt_row gt_center" headers="stat_2">25 (25%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;T2</td>
<td class="gt_row gt_center" headers="stat_1">25 (26%)</td>
<td class="gt_row gt_center" headers="stat_2">29 (28%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;T3</td>
<td class="gt_row gt_center" headers="stat_1">22 (22%)</td>
<td class="gt_row gt_center" headers="stat_2">21 (21%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;T4</td>
<td class="gt_row gt_center" headers="stat_1">23 (23%)</td>
<td class="gt_row gt_center" headers="stat_2">27 (26%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
</tbody><tfoot>
<tr class="gt_footnotes odd">
<td colspan="4" class="gt_footnote"><span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>1</sup></span> Median (Q1, Q3); n (%)</td>
</tr>
<tr class="gt_footnotes even">
<td colspan="4" class="gt_footnote"><span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>2</sup></span> Wilcoxon rank sum test; Pearson’s Chi-squared test</td>
</tr>
</tfoot>

</table>

</div>
</div>
</div>
<p>That’s the whole table. <code>tbl_summary()</code> picks median (IQR) for continuous variables and n (%) for categoricals; <code>add_p()</code> chooses an appropriate test for each row (Wilcoxon, chi-squared, Fisher) and reports the p-value. No manual test selection, no transcription.</p>
</section>
<section id="making-it-publication-ready" class="level2">
<h2 class="anchored" data-anchor-id="making-it-publication-ready">Making it publication-ready</h2>
<p>A few extra verbs turn it into something you can paste straight into a manuscript:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">trial <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-2">  dplyr<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;">select</span>(trt, age, grade, marker) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tbl_summary</span>(</span>
<span id="cb2-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> trt,</span>
<span id="cb2-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(age <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;">"Age (years)"</span>, marker <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;">"Marker (ng/mL)"</span>),</span>
<span id="cb2-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">statistic =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all_continuous</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;">"{mean} ({sd})"</span>),</span>
<span id="cb2-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">missing_text =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Missing"</span></span>
<span id="cb2-8">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_p</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_overall</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bold_labels</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">modify_caption</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"**Table 1. Baseline characteristics by treatment**"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="ztkwflrmgm" style="padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
<style>#ztkwflrmgm table {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#ztkwflrmgm thead, #ztkwflrmgm tbody, #ztkwflrmgm tfoot, #ztkwflrmgm tr, #ztkwflrmgm td, #ztkwflrmgm th {
  border-style: none;
}

#ztkwflrmgm p {
  margin: 0;
  padding: 0;
}

#ztkwflrmgm .gt_table {
  display: table;
  border-collapse: collapse;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 16px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
}

#ztkwflrmgm .gt_caption {
  padding-top: 4px;
  padding-bottom: 4px;
}

#ztkwflrmgm .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}

#ztkwflrmgm .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}

#ztkwflrmgm .gt_heading {
  background-color: #FFFFFF;
  text-align: center;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#ztkwflrmgm .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#ztkwflrmgm .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#ztkwflrmgm .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 6px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}

#ztkwflrmgm .gt_column_spanner_outer {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 4px;
  padding-right: 4px;
}

#ztkwflrmgm .gt_column_spanner_outer:first-child {
  padding-left: 0;
}

#ztkwflrmgm .gt_column_spanner_outer:last-child {
  padding-right: 0;
}

#ztkwflrmgm .gt_column_spanner {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  overflow-x: hidden;
  display: inline-block;
  width: 100%;
}

#ztkwflrmgm .gt_spanner_row {
  border-bottom-style: hidden;
}

#ztkwflrmgm .gt_group_heading {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  text-align: left;
}

#ztkwflrmgm .gt_empty_group_heading {
  padding: 0.5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: middle;
}

#ztkwflrmgm .gt_from_md > :first-child {
  margin-top: 0;
}

#ztkwflrmgm .gt_from_md > :last-child {
  margin-bottom: 0;
}

#ztkwflrmgm .gt_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  overflow-x: hidden;
}

#ztkwflrmgm .gt_stub {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
}

#ztkwflrmgm .gt_stub_row_group {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
  vertical-align: top;
}

#ztkwflrmgm .gt_row_group_first td {
  border-top-width: 2px;
}

#ztkwflrmgm .gt_row_group_first th {
  border-top-width: 2px;
}

#ztkwflrmgm .gt_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#ztkwflrmgm .gt_first_summary_row {
  border-top-style: solid;
  border-top-color: #D3D3D3;
}

#ztkwflrmgm .gt_first_summary_row.thick {
  border-top-width: 2px;
}

#ztkwflrmgm .gt_last_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#ztkwflrmgm .gt_grand_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#ztkwflrmgm .gt_first_grand_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-style: double;
  border-top-width: 6px;
  border-top-color: #D3D3D3;
}

#ztkwflrmgm .gt_last_grand_summary_row_top {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: double;
  border-bottom-width: 6px;
  border-bottom-color: #D3D3D3;
}

#ztkwflrmgm .gt_striped {
  background-color: rgba(128, 128, 128, 0.05);
}

#ztkwflrmgm .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#ztkwflrmgm .gt_footnotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#ztkwflrmgm .gt_footnote {
  margin: 0px;
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#ztkwflrmgm .gt_sourcenotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#ztkwflrmgm .gt_sourcenote {
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#ztkwflrmgm .gt_left {
  text-align: left;
}

#ztkwflrmgm .gt_center {
  text-align: center;
}

#ztkwflrmgm .gt_right {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#ztkwflrmgm .gt_font_normal {
  font-weight: normal;
}

#ztkwflrmgm .gt_font_bold {
  font-weight: bold;
}

#ztkwflrmgm .gt_font_italic {
  font-style: italic;
}

#ztkwflrmgm .gt_super {
  font-size: 65%;
}

#ztkwflrmgm .gt_footnote_marks {
  font-size: 75%;
  vertical-align: 0.4em;
  position: initial;
}

#ztkwflrmgm .gt_asterisk {
  font-size: 100%;
  vertical-align: 0;
}

#ztkwflrmgm .gt_indent_1 {
  text-indent: 5px;
}

#ztkwflrmgm .gt_indent_2 {
  text-indent: 10px;
}

#ztkwflrmgm .gt_indent_3 {
  text-indent: 15px;
}

#ztkwflrmgm .gt_indent_4 {
  text-indent: 20px;
}

#ztkwflrmgm .gt_indent_5 {
  text-indent: 25px;
}

#ztkwflrmgm .katex-display {
  display: inline-flex !important;
  margin-bottom: 0.75em !important;
}

#ztkwflrmgm div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {
  height: 0px !important;
}
</style>

<table class="gt_table caption-top table table-sm table-striped small" data-quarto-bootstrap="false">
<caption><strong>Table 1. Baseline characteristics by treatment</strong></caption>
<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="gt_col_headings header">
<th id="label" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col"><strong>Characteristic</strong></th>
<th id="stat_0" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>Overall</strong><br>
N = 200<span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>1</sup></span></th>
<th id="stat_1" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>Drug A</strong><br>
N = 98<span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>1</sup></span></th>
<th id="stat_2" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>Drug B</strong><br>
N = 102<span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>1</sup></span></th>
<th id="p.value" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>p-value</strong><span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>2</sup></span></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr class="odd">
<td class="gt_row gt_left" headers="label" style="font-weight: bold">Age (years)</td>
<td class="gt_row gt_center" headers="stat_0">47 (14)</td>
<td class="gt_row gt_center" headers="stat_1">47 (15)</td>
<td class="gt_row gt_center" headers="stat_2">47 (14)</td>
<td class="gt_row gt_center" headers="p.value">0.7</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;Missing</td>
<td class="gt_row gt_center" headers="stat_0">11</td>
<td class="gt_row gt_center" headers="stat_1">7</td>
<td class="gt_row gt_center" headers="stat_2">4</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label" style="font-weight: bold">Grade</td>
<td class="gt_row gt_center" headers="stat_0"><br>
</td>
<td class="gt_row gt_center" headers="stat_1"><br>
</td>
<td class="gt_row gt_center" headers="stat_2"><br>
</td>
<td class="gt_row gt_center" headers="p.value">0.9</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;I</td>
<td class="gt_row gt_center" headers="stat_0">68 (34%)</td>
<td class="gt_row gt_center" headers="stat_1">35 (36%)</td>
<td class="gt_row gt_center" headers="stat_2">33 (32%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;II</td>
<td class="gt_row gt_center" headers="stat_0">68 (34%)</td>
<td class="gt_row gt_center" headers="stat_1">32 (33%)</td>
<td class="gt_row gt_center" headers="stat_2">36 (35%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;III</td>
<td class="gt_row gt_center" headers="stat_0">64 (32%)</td>
<td class="gt_row gt_center" headers="stat_1">31 (32%)</td>
<td class="gt_row gt_center" headers="stat_2">33 (32%)</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label" style="font-weight: bold">Marker (ng/mL)</td>
<td class="gt_row gt_center" headers="stat_0">0.92 (0.86)</td>
<td class="gt_row gt_center" headers="stat_1">1.02 (0.89)</td>
<td class="gt_row gt_center" headers="stat_2">0.82 (0.83)</td>
<td class="gt_row gt_center" headers="p.value">0.085</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;Missing</td>
<td class="gt_row gt_center" headers="stat_0">10</td>
<td class="gt_row gt_center" headers="stat_1">6</td>
<td class="gt_row gt_center" headers="stat_2">4</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
</tbody><tfoot>
<tr class="gt_footnotes odd">
<td colspan="5" class="gt_footnote"><span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>1</sup></span> Mean (SD); n (%)</td>
</tr>
<tr class="gt_footnotes even">
<td colspan="5" class="gt_footnote"><span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>2</sup></span> Wilcoxon rank sum test; Pearson’s Chi-squared test</td>
</tr>
</tfoot>

</table>

</div>
</div>
</div>
<p>Here we switched continuous summaries to mean (SD), relabelled variables, added an overall column, and counted missing values explicitly instead of dropping them silently — a small honesty that reviewers notice.</p>
</section>
<section id="why-it-matters" class="level2">
<h2 class="anchored" data-anchor-id="why-it-matters">Why it matters</h2>
<p>The value isn’t saving five minutes once; it’s that the table is <strong>code</strong>. Clean a data point, rerun, and every number updates — including the tests and the percentages. There is no window where the manuscript and the data disagree. That’s the whole philosophy behind <a href="../services.html">how we work</a>, applied to the humblest table in the paper.</p>
<hr>
<p><em>More clinical recipes live in our <a href="../clinical-r.html">Clinical R toolkit</a>. Need this on your own data? <a href="../contact.html">Get in touch</a>.</em></p>


</section>

 ]]></description>
  <category>clinical</category>
  <category>biostatistics</category>
  <category>gtsummary</category>
  <category>reporting</category>
  <guid>https://rverseanalytics.com/posts/table1-baseline-characteristics-gtsummary.html</guid>
  <pubDate>Wed, 08 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>What to know before hiring an R consultant</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/hiring-an-r-consultant.html</link>
  <description><![CDATA[ 




<p>Hiring help with an analysis is easy; hiring help you don’t regret in six months is harder. The difference is rarely statistical skill — it’s how the work is <em>delivered</em>. Here is what we’d ask before signing anything.</p>
<section id="will-you-own-the-code-or-just-the-output" class="level2">
<h2 class="anchored" data-anchor-id="will-you-own-the-code-or-just-the-output">Will you own the code — or just the output?</h2>
<p>A results table is a dead end. A <strong>script that produces the table</strong> is an asset: rerun it on cleaned data, adapt it for the next study, hand it to a colleague. Ask explicitly whether you receive the code, whether it runs end-to-end from raw data, and whether you’re free to reuse it. If the answer is “we’ll send you the figures,” you’re renting, not owning.</p>
</section>
<section id="is-it-reproducible-or-a-pile-of-manual-steps" class="level2">
<h2 class="anchored" data-anchor-id="is-it-reproducible-or-a-pile-of-manual-steps">Is it reproducible, or a pile of manual steps?</h2>
<p>“Reproducible” has a concrete test: can someone else regenerate every number and figure with a single command? A good pipeline makes the cost of a data correction almost zero — rerun and you’re done. A bad one makes it a day of re-clicking. The economics compound over a project’s life:</p>
<div class="cell">
<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;">library</span>(ggplot2)</span>
<span id="cb1-2"></span>
<span id="cb1-3">reruns <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span></span>
<span id="cb1-4">manual      <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;">45</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> reruns          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ~45 min of clicking each time</span></span>
<span id="cb1-5">reproducible <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;">90</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> reruns     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one-off setup, then ~1 min per rerun</span></span>
<span id="cb1-6"></span>
<span id="cb1-7">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb1-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">reruns =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(reruns, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb1-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">minutes =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(manual, reproducible),</span>
<span id="cb1-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">workflow =</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;">"Manual"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Reproducible"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(reruns))</span>
<span id="cb1-11">)</span>
<span id="cb1-12"></span>
<span id="cb1-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(d, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(reruns, minutes, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> workflow)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Manual =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b02a37"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Reproducible =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb1-17">    <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;">"Why reproducibility pays off after the first correction"</span>,</span>
<span id="cb1-18">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of data updates / reruns"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cumulative minutes spent"</span>,</span>
<span id="cb1-19">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span></span>
<span id="cb1-20">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb1-23">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-rerun-cost" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-rerun-cost-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/hiring-an-r-consultant_files/figure-html/fig-rerun-cost-1.png" id="fig-rerun-cost" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-rerun-cost-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>The reproducible line starts higher — there’s real setup — and then barely moves. Any project touched more than once comes out ahead.</p>
</section>
<section id="is-the-scope-in-writing" class="level2">
<h2 class="anchored" data-anchor-id="is-the-scope-in-writing">Is the scope in writing?</h2>
<p>Vague scope is where consulting relationships go wrong. Before work starts you should have, in writing: the question, the data, the deliverable, the timeline and the price. Fixed-scope milestones beat an open-ended hourly meter for everyone — you know the cost, and the consultant knows what “done” means.</p>
</section>
<section id="will-there-be-a-handover" class="level2">
<h2 class="anchored" data-anchor-id="will-there-be-a-handover">Will there be a handover?</h2>
<p>The last hour of a good engagement is a walkthrough: here’s the code, here’s how to rerun it, here’s what to change if your data grows. Without it, you inherit a black box. With it, your team is genuinely more capable than before.</p>
<hr>
<p><em>This is exactly how we work — see <a href="../services.html">our services</a> or the <a href="../faq.html">FAQ</a> for the details, then <a href="../contact.html">get in touch</a>.</em></p>


</section>

 ]]></description>
  <category>consulting</category>
  <category>reproducibility</category>
  <category>workflow</category>
  <guid>https://rverseanalytics.com/posts/hiring-an-r-consultant.html</guid>
  <pubDate>Tue, 07 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Cohen’s d and effect size in R</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/cohens-d-effect-size-r.html</link>
  <description><![CDATA[ 




<p>A p-value tells you whether an effect is <em>there</em>; an effect size tells you how <em>big</em> it is. With a large enough sample even a meaningless difference becomes “significant,” which is why every result should report an effect size too. For two means, that’s usually <strong>Cohen’s d</strong>. (Planning a study? Effect size is the key input to our <a href="../tools/sample-size-calculator.html">sample size calculator</a>.)</p>
<section id="what-cohens-d-is" class="level2">
<h2 class="anchored" data-anchor-id="what-cohens-d-is">What Cohen’s d is</h2>
<p>Cohen’s <em>d</em> is the difference between two group means expressed in <strong>pooled standard deviation units</strong> — so it’s comparable across studies and scales. Rough conventions:</p>
<ul>
<li><em>d</em> ≈ 0.2 — small</li>
<li><em>d</em> ≈ 0.5 — medium</li>
<li><em>d</em> ≈ 0.8 — large</li>
</ul>
</section>
<section id="compute-it-in-r" class="level2">
<h2 class="anchored" data-anchor-id="compute-it-in-r">Compute it in R</h2>
<p>Base R doesn’t have a built-in, but it’s a three-line function. We’ll use the <code>sleep</code> dataset (extra hours of sleep under two drugs):</p>
<div class="cell">
<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">cohen_d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(a, b) {</span>
<span id="cb1-2">  n1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(a); n2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(b)</span>
<span id="cb1-3">  s_pooled <span class="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> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(a) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (n2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(b)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (n1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> n2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb1-4">  (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</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;">mean</span>(b)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> s_pooled</span>
<span id="cb1-5">}</span>
<span id="cb1-6"></span>
<span id="cb1-7">g1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sleep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>extra[sleep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb1-8">g2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sleep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>extra[sleep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb1-9"></span>
<span id="cb1-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cohen_d</span>(g2, g1)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.8321811</code></pre>
</div>
</div>
<p>A <em>d</em> of this size points to a substantial difference between the two drugs — regardless of whether the p-value happens to clear 0.05 at this sample size.</p>
</section>
<section id="p-value-vs-effect-size" class="level2">
<h2 class="anchored" data-anchor-id="p-value-vs-effect-size">p-value vs effect size</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t.test</span>(g2, g1, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">paired =</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>p.value  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># significance</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.00283289</code></pre>
</div>
<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;">cohen_d</span>(g2, g1)                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># magnitude</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.8321811</code></pre>
</div>
</div>
<p>These answer <strong>different questions</strong>. Report both: significance says “unlikely to be noise,” effect size says “and here’s how much it matters.” A tiny <em>d</em> with a tiny p-value (from a huge sample) is statistically significant but often practically irrelevant.</p>
</section>
<section id="reporting" class="level2">
<h2 class="anchored" data-anchor-id="reporting">Reporting</h2>
<p>State the effect size with a confidence interval, and interpret it in the units your audience cares about — a “medium” <em>d</em> means little to a clinician until you translate it back into real outcomes.</p>
<hr>
<p><em>Want effects reported and interpreted properly, not just p-values? <a href="../services.html">That’s how we work.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>effect-size</category>
  <category>r-tutorial</category>
  <guid>https://rverseanalytics.com/posts/cohens-d-effect-size-r.html</guid>
  <pubDate>Mon, 06 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Sensitivity, specificity, PPV and NPV in R — and why prevalence changes everything</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/diagnostic-test-accuracy-r.html</link>
  <description><![CDATA[ 




<p>When you evaluate a diagnostic or screening test, four numbers do most of the work — and two of them quietly depend on something the test can’t control: how common the disease is. Here’s the full calculation in base R, no packages required.</p>
<section id="from-a-22-table-to-the-metrics" class="level2">
<h2 class="anchored" data-anchor-id="from-a-22-table-to-the-metrics">From a 2×2 table to the metrics</h2>
<p>Start with the counts of test result against true disease status:</p>
<div class="cell">
<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">tp <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;">90</span>; fp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># test positive: disease present / absent</span></span>
<span id="cb1-2">fn <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;">20</span>; tn <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;">180</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># test negative: disease present / absent</span></span>
<span id="cb1-3"></span>
<span id="cb1-4">metrics <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>(tp, fp, fn, tn) {</span>
<span id="cb1-5">  sens <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (tp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fn)</span>
<span id="cb1-6">  spec <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tn <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (tn <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fp)</span>
<span id="cb1-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb1-8">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Sensitivity =</span> sens,</span>
<span id="cb1-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Specificity =</span> spec,</span>
<span id="cb1-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">PPV =</span> tp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (tp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fp),</span>
<span id="cb1-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">NPV =</span> tn <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (tn <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fn),</span>
<span id="cb1-12">    <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;">LR+</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> sens <span 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> spec),</span>
<span id="cb1-13">    <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;">LR-</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> (<span class="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> sens) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> spec</span>
<span id="cb1-14">  )</span>
<span id="cb1-15">}</span>
<span id="cb1-16"></span>
<span id="cb1-17"><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;">metrics</span>(tp, fp, fn, tn), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Sensitivity Specificity         PPV         NPV         LR+         LR- 
      0.818       0.947       0.900       0.900      15.545       0.192 </code></pre>
</div>
</div>
<p><strong>Sensitivity</strong> and <strong>specificity</strong> are properties of the test itself. <strong>PPV</strong> and <strong>NPV</strong> — the questions patients actually care about (“I tested positive, do I have it?”) — are not: they shift with prevalence. <strong>Likelihood ratios</strong> neatly combine sensitivity and specificity and feed directly into Bayesian updating of pre-test odds.</p>
</section>
<section id="watch-prevalence-move-the-predictive-values" class="level2">
<h2 class="anchored" data-anchor-id="watch-prevalence-move-the-predictive-values">Watch prevalence move the predictive values</h2>
<p>Hold sensitivity and specificity fixed and sweep prevalence from rare to common:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb3-2"></span>
<span id="cb3-3">sens <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.90</span>; spec <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.95</span></span>
<span id="cb3-4">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;">seq</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.5</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;">300</span>)</span>
<span id="cb3-5">ppv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (sens <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> prev) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (sens <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> prev <span 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> spec) <span 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> prev))</span>
<span id="cb3-6">npv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (spec <span 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> prev)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (spec <span 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> prev) <span 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> sens) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> prev)</span>
<span id="cb3-7"></span>
<span id="cb3-8">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb3-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prevalence =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(prev, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb3-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(ppv, npv),</span>
<span id="cb3-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metric =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">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;">"PPV"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NPV"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(prev))</span>
<span id="cb3-12">)</span>
<span id="cb3-13"></span>
<span id="cb3-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(d, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(prevalence, value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> metric)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">PPV =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">NPV =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>percent, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">limits =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>percent) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb3-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;">"Predictive values depend on prevalence (sens = 90%, spec = 95%)"</span>,</span>
<span id="cb3-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;">"Disease prevalence"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predictive value"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span></span>
<span id="cb3-22">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-24">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb3-25">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-prev" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-prev-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/diagnostic-test-accuracy-r_files/figure-html/fig-prev-1.png" id="fig-prev" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-prev-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>At 1% prevalence a “positive” from this excellent test is more likely to be a false alarm than a true case — the PPV is low even though sensitivity and specificity are high. Move to a specialist clinic where a third of patients truly have the disease and the same test’s PPV soars.</p>
</section>
<section id="the-takeaway" class="level2">
<h2 class="anchored" data-anchor-id="the-takeaway">The takeaway</h2>
<p>Quote sensitivity and specificity to describe the test; quote PPV and NPV <em>with the prevalence they assume</em>, or you’ll mislead. Better still, present predictive values across the plausible prevalence range — exactly what the <a href="../demos.html">diagnostic-test calculator</a> in our live demos does interactively.</p>
<hr>
<p><em>Part of our <a href="../clinical-r.html">Clinical R toolkit</a>. Evaluating a test on your own data? <a href="../contact.html">Let’s talk.</a></em></p>


</section>

 ]]></description>
  <category>clinical</category>
  <category>biostatistics</category>
  <category>diagnostics</category>
  <guid>https://rverseanalytics.com/posts/diagnostic-test-accuracy-r.html</guid>
  <pubDate>Sun, 05 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Linear regression in R: how to read the output</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/linear-regression-interpreting-output-r.html</link>
  <description><![CDATA[ 




<p><code>lm()</code> is one of the most-used functions in R, and its <code>summary()</code> packs a lot into a small space. Here’s how to read every piece. (Predicting a binary outcome instead? See <a href="../posts/logistic-regression-odds-ratios-roc.html">logistic regression</a>.)</p>
<section id="fit-the-model" class="level2">
<h2 class="anchored" data-anchor-id="fit-the-model">Fit the model</h2>
<p>We’ll predict fuel economy (<code>mpg</code>) from weight and horsepower using the built-in <code>mtcars</code>:</p>
<div class="cell">
<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">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>(mpg <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> wt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> hp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> mtcars)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(fit)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
Call:
lm(formula = mpg ~ wt + hp, data = mtcars)

Residuals:
   Min     1Q Median     3Q    Max 
-3.941 -1.600 -0.182  1.050  5.854 

Coefficients:
            Estimate Std. Error t value Pr(&gt;|t|)    
(Intercept) 37.22727    1.59879  23.285  &lt; 2e-16 ***
wt          -3.87783    0.63273  -6.129 1.12e-06 ***
hp          -0.03177    0.00903  -3.519  0.00145 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.593 on 29 degrees of freedom
Multiple R-squared:  0.8268,    Adjusted R-squared:  0.8148 
F-statistic: 69.21 on 2 and 29 DF,  p-value: 9.109e-12</code></pre>
</div>
</div>
</section>
<section id="reading-the-summary" class="level2">
<h2 class="anchored" data-anchor-id="reading-the-summary">Reading the summary</h2>
<ul>
<li><strong>Coefficients (<code>Estimate</code>)</strong> — the change in <code>mpg</code> for a one-unit increase in that predictor, <em>holding the others constant</em>. Here each 1,000 lb of weight (<code>wt</code>) costs several mpg.</li>
<li><strong><code>Pr(&gt;|t|)</code></strong> — the p-value for “this coefficient is zero.” Small means the predictor carries information beyond the others.</li>
<li><strong><code>Multiple R-squared</code></strong> — the share of variance in <code>mpg</code> explained by the model. <strong>Adjusted R-squared</strong> penalises extra predictors and is the fairer figure to compare models.</li>
<li><strong>Residual standard error</strong> — the typical size of the model’s prediction errors, in mpg.</li>
</ul>
</section>
<section id="a-tidy-table" class="level2">
<h2 class="anchored" data-anchor-id="a-tidy-table">A tidy table</h2>
<p><code>broom</code> turns the model into data frames that are easy to report or plot:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(broom)</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tidy</span>(fit, <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 class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># coefficients + 95% CIs</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 3 × 7
  term        estimate std.error statistic  p.value conf.low conf.high
  &lt;chr&gt;          &lt;dbl&gt;     &lt;dbl&gt;     &lt;dbl&gt;    &lt;dbl&gt;    &lt;dbl&gt;     &lt;dbl&gt;
1 (Intercept)  37.2      1.60        23.3  2.57e-20  34.0      40.5   
2 wt           -3.88     0.633       -6.13 1.12e- 6  -5.17     -2.58  
3 hp           -0.0318   0.00903     -3.52 1.45e- 3  -0.0502   -0.0133</code></pre>
</div>
<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;">glance</span>(fit)                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># model-level stats</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 1 × 12
  r.squared adj.r.squared sigma statistic  p.value    df logLik   AIC   BIC
      &lt;dbl&gt;         &lt;dbl&gt; &lt;dbl&gt;     &lt;dbl&gt;    &lt;dbl&gt; &lt;dbl&gt;  &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt;
1     0.827         0.815  2.59      69.2 9.11e-12     2  -74.3  157.  163.
# ℹ 3 more variables: deviance &lt;dbl&gt;, df.residual &lt;int&gt;, nobs &lt;int&gt;</code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(mtcars, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(wt, mpg)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_smooth</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lm"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se =</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;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed22"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<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;">"mpg vs weight, with linear fit"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Weight (1000 lb)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mpg"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-lm" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-lm-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/linear-regression-interpreting-output-r_files/figure-html/fig-lm-1.png" id="fig-lm" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-lm-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="dont-skip-the-diagnostics" class="level2">
<h2 class="anchored" data-anchor-id="dont-skip-the-diagnostics">Don’t skip the diagnostics</h2>
<p>A regression is only trustworthy if its assumptions hold. Run <code>plot(fit)</code> to check linearity, constant variance and <a href="../posts/checking-normality-r.html">normal residuals</a> before you interpret a single coefficient.</p>
<hr>
<p><em>Regression with confounders, interactions or a report to produce? <a href="../services.html">That’s our statistical analysis service.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>regression</category>
  <category>r-tutorial</category>
  <guid>https://rverseanalytics.com/posts/linear-regression-interpreting-output-r.html</guid>
  <pubDate>Sat, 04 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>R vs Python for statistical consulting: an honest take</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/r-vs-python-statistical-consulting.html</link>
  <description><![CDATA[ 




<p>We work in R, so treat this with appropriate suspicion — but we’ve written plenty of Python too, and the honest answer is <em>it depends on what the work is for</em>. For the kind of consulting we do — inference, study analysis, publication-bound reporting — R keeps winning on specifics, not slogans.</p>
<section id="where-python-is-the-better-call" class="level2">
<h2 class="anchored" data-anchor-id="where-python-is-the-better-call">Where Python is the better call</h2>
<p>Be fair first. If the deliverable is a production ML service, a deep-learning model, or code that has to live inside a larger Python application, use Python. The tooling, the deployment story and the surrounding ecosystem are simply built for that. Choosing R there would be stubbornness.</p>
</section>
<section id="where-r-pulls-ahead" class="level2">
<h2 class="anchored" data-anchor-id="where-r-pulls-ahead">Where R pulls ahead</h2>
<p>For classical statistics, R is the reference implementation, not a port. Methods appear on CRAN as researchers publish them; mixed-effects models (<code>lme4</code>), survival analysis (<code>survival</code>) and a thousand niche tests are first-class, battle-tested and consistent. And two things matter enormously for consulting deliverables:</p>
<ul>
<li><strong><code>ggplot2</code></strong> for figures a journal will accept without a fight.</li>
<li><strong>Quarto / R Markdown</strong> for reports that regenerate from data with one command.</li>
</ul>
<p>A quick illustration — a full model summary and diagnostics are one line away, with output designed to be <em>read</em>, not parsed:</p>
<div class="cell">
<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">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>(mpg <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> wt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> hp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> mtcars)</span>
<span id="cb1-2"><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-stdout">
<pre><code>               Estimate Std. Error   t value     Pr(&gt;|t|)
(Intercept) 37.22727012 1.59878754 23.284689 2.565459e-20
wt          -3.87783074 0.63273349 -6.128695 1.119647e-06
hp          -0.03177295 0.00902971 -3.518712 1.451229e-03</code></pre>
</div>
</div>
<p>That coefficient table, the assumption checks, and a publication figure all come from the same object, in the same session, in a language whose defaults were chosen by statisticians.</p>
</section>
<section id="the-real-answer-match-the-tool-to-the-deliverable" class="level2">
<h2 class="anchored" data-anchor-id="the-real-answer-match-the-tool-to-the-deliverable">The real answer: match the tool to the deliverable</h2>
<p>The tribal “R vs Python” framing is mostly noise. The useful question is what has to exist at the end:</p>
<ul>
<li>A <strong>peer-reviewed results section</strong>, APA tables or clinical figures → R.</li>
<li>A <strong>reproducible report</strong> that reruns monthly → R (or Quarto with either).</li>
<li>A <strong>model embedded in a product</strong> or a deep-learning pipeline → Python.</li>
<li>A <strong>team already fluent in one</strong> → usually that one, unless the deliverable demands otherwise.</li>
</ul>
<p>We pick R for our niche because it makes the statistical, reproducible, publication-ready deliverable the path of least resistance. Different niche, different answer — and a consultant who tells you otherwise is selling, not advising.</p>
<hr>
<p><em>Curious whether R fits your project? <a href="../contact.html">Tell us what you’re trying to produce</a> and we’ll give you a straight answer — even if it’s “use Python.”</em></p>


</section>

 ]]></description>
  <category>consulting</category>
  <category>R</category>
  <category>workflow</category>
  <guid>https://rverseanalytics.com/posts/r-vs-python-statistical-consulting.html</guid>
  <pubDate>Fri, 03 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Logistic regression in R: odds ratios and ROC/AUC, done right</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/logistic-regression-odds-ratios-roc.html</link>
  <description><![CDATA[ 




<p>For a yes/no clinical outcome — responded or not, readmitted or not — logistic regression is the workhorse. But a model isn’t finished at the coefficient table. You need <strong>adjusted odds ratios</strong> to interpret effects and a <strong>ROC curve with AUC</strong> to judge how well the model actually separates the two groups.</p>
<section id="fit-the-model" class="level2">
<h2 class="anchored" data-anchor-id="fit-the-model">Fit the model</h2>
<p>Using the <code>trial</code> dataset (<code>response</code> = tumour response), we adjust for age, marker level and disease stage. Fit on complete cases so the model and the ROC use the same rows:</p>
<div class="cell">
<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;">library</span>(gtsummary)</span>
<span id="cb1-2"></span>
<span id="cb1-3">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;">na.omit</span>(trial[, <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;">"response"</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;">"marker"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"stage"</span>)])</span>
<span id="cb1-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;">glm</span>(response <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> marker <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> stage, <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;">family =</span> binomial)</span></code></pre></div></div>
</div>
</section>
<section id="odds-ratios-that-read-cleanly" class="level2">
<h2 class="anchored" data-anchor-id="odds-ratios-that-read-cleanly">Odds ratios that read cleanly</h2>
<p><code>tbl_regression(exponentiate = TRUE)</code> turns the raw log-odds coefficients into odds ratios with confidence intervals and p-values — the format a journal expects:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tbl_regression</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">exponentiate =</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="cb2-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bold_p</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">modify_caption</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"**Adjusted odds ratios for tumour response**"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="caxiowiwnm" style="padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
<style>#caxiowiwnm table {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#caxiowiwnm thead, #caxiowiwnm tbody, #caxiowiwnm tfoot, #caxiowiwnm tr, #caxiowiwnm td, #caxiowiwnm th {
  border-style: none;
}

#caxiowiwnm p {
  margin: 0;
  padding: 0;
}

#caxiowiwnm .gt_table {
  display: table;
  border-collapse: collapse;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 16px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
}

#caxiowiwnm .gt_caption {
  padding-top: 4px;
  padding-bottom: 4px;
}

#caxiowiwnm .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}

#caxiowiwnm .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}

#caxiowiwnm .gt_heading {
  background-color: #FFFFFF;
  text-align: center;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#caxiowiwnm .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#caxiowiwnm .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#caxiowiwnm .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 6px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}

#caxiowiwnm .gt_column_spanner_outer {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 4px;
  padding-right: 4px;
}

#caxiowiwnm .gt_column_spanner_outer:first-child {
  padding-left: 0;
}

#caxiowiwnm .gt_column_spanner_outer:last-child {
  padding-right: 0;
}

#caxiowiwnm .gt_column_spanner {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  overflow-x: hidden;
  display: inline-block;
  width: 100%;
}

#caxiowiwnm .gt_spanner_row {
  border-bottom-style: hidden;
}

#caxiowiwnm .gt_group_heading {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  text-align: left;
}

#caxiowiwnm .gt_empty_group_heading {
  padding: 0.5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: middle;
}

#caxiowiwnm .gt_from_md > :first-child {
  margin-top: 0;
}

#caxiowiwnm .gt_from_md > :last-child {
  margin-bottom: 0;
}

#caxiowiwnm .gt_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  overflow-x: hidden;
}

#caxiowiwnm .gt_stub {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
}

#caxiowiwnm .gt_stub_row_group {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
  vertical-align: top;
}

#caxiowiwnm .gt_row_group_first td {
  border-top-width: 2px;
}

#caxiowiwnm .gt_row_group_first th {
  border-top-width: 2px;
}

#caxiowiwnm .gt_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#caxiowiwnm .gt_first_summary_row {
  border-top-style: solid;
  border-top-color: #D3D3D3;
}

#caxiowiwnm .gt_first_summary_row.thick {
  border-top-width: 2px;
}

#caxiowiwnm .gt_last_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#caxiowiwnm .gt_grand_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#caxiowiwnm .gt_first_grand_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-style: double;
  border-top-width: 6px;
  border-top-color: #D3D3D3;
}

#caxiowiwnm .gt_last_grand_summary_row_top {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: double;
  border-bottom-width: 6px;
  border-bottom-color: #D3D3D3;
}

#caxiowiwnm .gt_striped {
  background-color: rgba(128, 128, 128, 0.05);
}

#caxiowiwnm .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#caxiowiwnm .gt_footnotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#caxiowiwnm .gt_footnote {
  margin: 0px;
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#caxiowiwnm .gt_sourcenotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#caxiowiwnm .gt_sourcenote {
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#caxiowiwnm .gt_left {
  text-align: left;
}

#caxiowiwnm .gt_center {
  text-align: center;
}

#caxiowiwnm .gt_right {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#caxiowiwnm .gt_font_normal {
  font-weight: normal;
}

#caxiowiwnm .gt_font_bold {
  font-weight: bold;
}

#caxiowiwnm .gt_font_italic {
  font-style: italic;
}

#caxiowiwnm .gt_super {
  font-size: 65%;
}

#caxiowiwnm .gt_footnote_marks {
  font-size: 75%;
  vertical-align: 0.4em;
  position: initial;
}

#caxiowiwnm .gt_asterisk {
  font-size: 100%;
  vertical-align: 0;
}

#caxiowiwnm .gt_indent_1 {
  text-indent: 5px;
}

#caxiowiwnm .gt_indent_2 {
  text-indent: 10px;
}

#caxiowiwnm .gt_indent_3 {
  text-indent: 15px;
}

#caxiowiwnm .gt_indent_4 {
  text-indent: 20px;
}

#caxiowiwnm .gt_indent_5 {
  text-indent: 25px;
}

#caxiowiwnm .katex-display {
  display: inline-flex !important;
  margin-bottom: 0.75em !important;
}

#caxiowiwnm div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {
  height: 0px !important;
}
</style>

<table class="gt_table caption-top table table-sm table-striped small" data-quarto-bootstrap="false">
<caption><strong>Adjusted odds ratios for tumour response</strong></caption>
<colgroup>
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
</colgroup>
<thead>
<tr class="gt_col_headings header">
<th id="label" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col"><strong>Characteristic</strong></th>
<th id="estimate" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>OR</strong></th>
<th id="conf.low" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>95% CI</strong></th>
<th id="p.value" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>p-value</strong></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr class="odd">
<td class="gt_row gt_left" headers="label">Age</td>
<td class="gt_row gt_center" headers="estimate">1.02</td>
<td class="gt_row gt_center" headers="conf.low">1.00, 1.04</td>
<td class="gt_row gt_center" headers="p.value">0.11</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">Marker Level (ng/mL)</td>
<td class="gt_row gt_center" headers="estimate">1.38</td>
<td class="gt_row gt_center" headers="conf.low">0.95, 2.03</td>
<td class="gt_row gt_center" headers="p.value">0.092</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">T Stage</td>
<td class="gt_row gt_center" headers="estimate"><br>
</td>
<td class="gt_row gt_center" headers="conf.low"><br>
</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;T1</td>
<td class="gt_row gt_center" headers="estimate">—</td>
<td class="gt_row gt_center" headers="conf.low">—</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;T2</td>
<td class="gt_row gt_center" headers="estimate">0.46</td>
<td class="gt_row gt_center" headers="conf.low">0.18, 1.13</td>
<td class="gt_row gt_center" headers="p.value">0.094</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;T3</td>
<td class="gt_row gt_center" headers="estimate">0.87</td>
<td class="gt_row gt_center" headers="conf.low">0.34, 2.21</td>
<td class="gt_row gt_center" headers="p.value">0.8</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;T4</td>
<td class="gt_row gt_center" headers="estimate">0.65</td>
<td class="gt_row gt_center" headers="conf.low">0.26, 1.62</td>
<td class="gt_row gt_center" headers="p.value">0.4</td>
</tr>
</tbody><tfoot>
<tr class="gt_sourcenotes odd">
<td colspan="4" class="gt_sourcenote">Abbreviations: CI = Confidence Interval, OR = Odds Ratio</td>
</tr>
</tfoot>

</table>

</div>
</div>
</div>
<p>An odds ratio above 1 raises the odds of response, below 1 lowers them; the confidence interval tells you how sure you can be. Because these are <em>adjusted</em>, each is the effect of that variable holding the others fixed.</p>
</section>
<section id="how-well-does-it-discriminate" class="level2">
<h2 class="anchored" data-anchor-id="how-well-does-it-discriminate">How well does it discriminate?</h2>
<p>Significant predictors don’t guarantee a useful model. The ROC curve plots sensitivity against 1 − specificity across every threshold, and the area under it (AUC) summarises discrimination in a single number — 0.5 is a coin flip, 1.0 is perfect:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(pROC)</span>
<span id="cb3-2"></span>
<span id="cb3-3">roc_obj <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">roc</span>(d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>response, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fitted</span>(fit), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb3-4"></span>
<span id="cb3-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(roc_obj, <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;">"#2f6fed"</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;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy.axes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb3-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;">"1 - Specificity"</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;">"Sensitivity"</span>,</span>
<span id="cb3-7">     <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;">"ROC curve"</span>)</span>
<span id="cb3-8"><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;">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;">"#8a93a6"</span>)</span>
<span id="cb3-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">text</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.2</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AUC = %.3f"</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;">auc</span>(roc_obj))),</span>
<span id="cb3-10">     <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;">"#1b2a4a"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">font =</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;">1.3</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-roc" class="quarto-float quarto-figure quarto-figure-center anchored" width="576">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-roc-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/logistic-regression-odds-ratios-roc_files/figure-html/fig-roc-1.png" id="fig-roc" class="img-fluid figure-img" width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-roc-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>Report the AUC with a confidence interval (<code>ci.auc(roc_obj)</code>) and, if the model will guide decisions, calibration too — discrimination and calibration answer different questions.</p>
</section>
<section id="the-takeaway" class="level2">
<h2 class="anchored" data-anchor-id="the-takeaway">The takeaway</h2>
<p>Odds ratios tell you <em>which factors matter and by how much</em>; the AUC tells you <em>whether the model is worth using at all</em>. A complete logistic analysis reports both — and, ideally, is reproducible from raw data to figure in one script.</p>
<hr>
<p><em>See this alongside survival and diagnostic-test recipes in our <a href="../clinical-r.html">Clinical R toolkit</a>.</em></p>


</section>

 ]]></description>
  <category>clinical</category>
  <category>biostatistics</category>
  <category>regression</category>
  <category>pROC</category>
  <guid>https://rverseanalytics.com/posts/logistic-regression-odds-ratios-roc.html</guid>
  <pubDate>Thu, 02 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Chi-square test of independence in R</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/chi-square-test-independence-r.html</link>
  <description><![CDATA[ 




<p>When both of your variables are categorical, the chi-square test of independence asks: are they associated, or independent? Here’s the full workflow in R. (Unsure this is the right test? Check the <a href="../which-test.html">which-test tool</a>.)</p>
<section id="build-the-contingency-table" class="level2">
<h2 class="anchored" data-anchor-id="build-the-contingency-table">Build the contingency table</h2>
<p>We’ll use the built-in <code>HairEyeColor</code> data, collapsed to a hair-colour × eye-colour table:</p>
<div class="cell">
<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">tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(HairEyeColor, <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>), sum)</span>
<span id="cb1-2">tab</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>       Eye
Hair    Brown Blue Hazel Green
  Black    68   20    15     5
  Brown   119   84    54    29
  Red      26   17    14    14
  Blond     7   94    10    16</code></pre>
</div>
</div>
</section>
<section id="run-the-test" class="level2">
<h2 class="anchored" data-anchor-id="run-the-test">Run the test</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">chisq.test</span>(tab)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
    Pearson's Chi-squared test

data:  tab
X-squared = 138.29, df = 9, p-value &lt; 2.2e-16</code></pre>
</div>
</div>
<p>A small p-value means hair colour and eye colour are <strong>not</strong> independent — there’s an association. The test compares the observed counts to the counts you’d expect if the two variables were unrelated.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mosaicplot</span>(tab, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</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;">"#1b2a4a"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5aa0ff"</span>),</span>
<span id="cb5-2">           <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;">"Hair vs eye colour"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">las =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-mosaic" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-mosaic-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/chi-square-test-independence-r_files/figure-html/fig-mosaic-1.png" id="fig-mosaic" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-mosaic-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>The mosaic plot makes the association visible — tile areas are proportional to counts, and the pattern departs clearly from a plain grid.</p>
</section>
<section id="when-to-use-fishers-exact-test-instead" class="level2">
<h2 class="anchored" data-anchor-id="when-to-use-fishers-exact-test-instead">When to use Fisher’s exact test instead</h2>
<p>The chi-square approximation gets unreliable when <strong>expected</strong> cell counts are small (a common rule: any expected count &lt; 5). R even warns you. In that case, use the exact alternative:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fisher.test</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;">8</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 class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
    Fisher's Exact Test for Count Data

data:  matrix(c(8, 2, 1, 9), nrow = 2)
p-value = 0.005477
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
    2.057999 1740.081669
sample estimates:
odds ratio 
  27.32632 </code></pre>
</div>
</div>
<p>Check expected counts with <code>chisq.test(tab)$expected</code>, and switch to <code>fisher.test()</code> for small tables.</p>
</section>
<section id="reporting-it" class="level2">
<h2 class="anchored" data-anchor-id="reporting-it">Reporting it</h2>
<p>Report the statistic, degrees of freedom, p-value and — crucially — an effect size such as Cramér’s V, since a large sample can make a trivial association “significant.”</p>
<hr>
<p><em>Categorical data with more structure than a single table? <a href="../services.html">That’s where we come in.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>categorical-data</category>
  <category>r-tutorial</category>
  <guid>https://rverseanalytics.com/posts/chi-square-test-independence-r.html</guid>
  <pubDate>Wed, 01 Jul 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Why Welch’s t-test should be your default</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/welch-vs-student-t.html</link>
  <description><![CDATA[ 




<p>A question we get surprisingly often: <em>“Levene’s test was significant — can I still run a t-test?”</em> Yes — the Welch version. In fact, there is a good argument for using Welch <strong>by default</strong>, and a small simulation makes the point better than any citation.</p>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<p>Two groups, equal means (so the null hypothesis is true), but one group is twice as variable and half as large. Any test with a nominal α of .05 should reject in about 5% of runs.</p>
<div class="cell">
<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;">2026</span>)</span>
<span id="cb1-2"></span>
<span id="cb1-3">sim_once <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="cb1-4">  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;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>, <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;">50</span>, <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 class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># larger, tighter group</span></span>
<span id="cb1-5">  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;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <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;">50</span>, <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;">10</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># smaller, noisier group</span></span>
<span id="cb1-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb1-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">student =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t.test</span>(a, b, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var.equal =</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>p.value,</span>
<span id="cb1-8">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">welch   =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t.test</span>(a, b, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var.equal =</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>p.value</span>
<span id="cb1-9">  )</span>
<span id="cb1-10">}</span>
<span id="cb1-11"></span>
<span id="cb1-12">res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sim_once</span>()))</span>
<span id="cb1-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colMeans</span>(res <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>student   welch 
 0.1088  0.0507 </code></pre>
</div>
</div>
<p>The Student’s t-test rejects a <em>true</em> null far more often than the promised 5%, while Welch stays honest.</p>
</section>
<section id="seeing-it" class="level2">
<h2 class="anchored" data-anchor-id="seeing-it">Seeing it</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb3-2"></span>
<span id="cb3-3">rates <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb3-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test =</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;">"Student's t"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Welch's t"</span>),</span>
<span id="cb3-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rate =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colMeans</span>(res <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb3-6">)</span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(rates, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(test, rate, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> test)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_col</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.55</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.legend =</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>
<span id="cb3-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<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;">percent_format</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">accuracy =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb3-14">    <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;">"Empirical Type I error under unequal variances and group sizes"</span>,</span>
<span id="cb3-15">    <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;">"10,000 simulated studies; dashed line marks the nominal 5% level"</span>,</span>
<span id="cb3-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"False positive rate"</span></span>
<span id="cb3-17">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-18">  <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="cb3-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-type1" class="quarto-float quarto-figure quarto-figure-center anchored" width="672">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-type1-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/welch-vs-student-t_files/figure-html/fig-type1-1.png" id="fig-type1" class="img-fluid figure-img" width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-type1-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="the-takeaway" class="level2">
<h2 class="anchored" data-anchor-id="the-takeaway">The takeaway</h2>
<p>When variances and group sizes are both unequal, the classic pooled-variance t-test can be badly miscalibrated — here it roughly doubles the false-positive rate. Welch’s test handles this case and behaves almost identically when variances <em>are</em> equal. That asymmetry is why <code>t.test()</code> in R uses Welch <strong>by default</strong>, and why we do too.</p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>simulation</category>
  <guid>https://rverseanalytics.com/posts/welch-vs-student-t.html</guid>
  <pubDate>Tue, 30 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Cox proportional hazards in R — and the assumption you must check</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/cox-proportional-hazards-r.html</link>
  <description><![CDATA[ 




<p>Cox proportional hazards regression is the standard tool for time-to-event outcomes with covariates — survival adjusted for age, treatment, stage. It’s easy to fit and easy to misuse, because its central assumption is easy to forget: hazard ratios are assumed <strong>constant over time</strong>. If that fails, your single hazard ratio is an average of a moving target.</p>
<section id="fit-the-model" class="level2">
<h2 class="anchored" data-anchor-id="fit-the-model">Fit the model</h2>
<p>We’ll use the <code>trial</code> dataset (<code>ttdeath</code> = time, <code>death</code> = event) and adjust for treatment, age and grade:</p>
<div class="cell">
<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;">library</span>(survival)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(gtsummary)</span>
<span id="cb1-3"></span>
<span id="cb1-4">cx <span class="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 class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Surv</span>(ttdeath, death) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> trt <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> grade, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> trial)</span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tbl_regression</span>(cx, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">exponentiate =</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="cb1-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bold_p</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb1-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">modify_caption</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"**Hazard ratios for death**"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="lkvkubpjoe" style="padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
<style>#lkvkubpjoe table {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#lkvkubpjoe thead, #lkvkubpjoe tbody, #lkvkubpjoe tfoot, #lkvkubpjoe tr, #lkvkubpjoe td, #lkvkubpjoe th {
  border-style: none;
}

#lkvkubpjoe p {
  margin: 0;
  padding: 0;
}

#lkvkubpjoe .gt_table {
  display: table;
  border-collapse: collapse;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 16px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
}

#lkvkubpjoe .gt_caption {
  padding-top: 4px;
  padding-bottom: 4px;
}

#lkvkubpjoe .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}

#lkvkubpjoe .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}

#lkvkubpjoe .gt_heading {
  background-color: #FFFFFF;
  text-align: center;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#lkvkubpjoe .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#lkvkubpjoe .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#lkvkubpjoe .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 6px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}

#lkvkubpjoe .gt_column_spanner_outer {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 4px;
  padding-right: 4px;
}

#lkvkubpjoe .gt_column_spanner_outer:first-child {
  padding-left: 0;
}

#lkvkubpjoe .gt_column_spanner_outer:last-child {
  padding-right: 0;
}

#lkvkubpjoe .gt_column_spanner {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  overflow-x: hidden;
  display: inline-block;
  width: 100%;
}

#lkvkubpjoe .gt_spanner_row {
  border-bottom-style: hidden;
}

#lkvkubpjoe .gt_group_heading {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  text-align: left;
}

#lkvkubpjoe .gt_empty_group_heading {
  padding: 0.5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: middle;
}

#lkvkubpjoe .gt_from_md > :first-child {
  margin-top: 0;
}

#lkvkubpjoe .gt_from_md > :last-child {
  margin-bottom: 0;
}

#lkvkubpjoe .gt_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  overflow-x: hidden;
}

#lkvkubpjoe .gt_stub {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
}

#lkvkubpjoe .gt_stub_row_group {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
  vertical-align: top;
}

#lkvkubpjoe .gt_row_group_first td {
  border-top-width: 2px;
}

#lkvkubpjoe .gt_row_group_first th {
  border-top-width: 2px;
}

#lkvkubpjoe .gt_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#lkvkubpjoe .gt_first_summary_row {
  border-top-style: solid;
  border-top-color: #D3D3D3;
}

#lkvkubpjoe .gt_first_summary_row.thick {
  border-top-width: 2px;
}

#lkvkubpjoe .gt_last_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#lkvkubpjoe .gt_grand_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#lkvkubpjoe .gt_first_grand_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-style: double;
  border-top-width: 6px;
  border-top-color: #D3D3D3;
}

#lkvkubpjoe .gt_last_grand_summary_row_top {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: double;
  border-bottom-width: 6px;
  border-bottom-color: #D3D3D3;
}

#lkvkubpjoe .gt_striped {
  background-color: rgba(128, 128, 128, 0.05);
}

#lkvkubpjoe .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#lkvkubpjoe .gt_footnotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#lkvkubpjoe .gt_footnote {
  margin: 0px;
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#lkvkubpjoe .gt_sourcenotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#lkvkubpjoe .gt_sourcenote {
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#lkvkubpjoe .gt_left {
  text-align: left;
}

#lkvkubpjoe .gt_center {
  text-align: center;
}

#lkvkubpjoe .gt_right {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#lkvkubpjoe .gt_font_normal {
  font-weight: normal;
}

#lkvkubpjoe .gt_font_bold {
  font-weight: bold;
}

#lkvkubpjoe .gt_font_italic {
  font-style: italic;
}

#lkvkubpjoe .gt_super {
  font-size: 65%;
}

#lkvkubpjoe .gt_footnote_marks {
  font-size: 75%;
  vertical-align: 0.4em;
  position: initial;
}

#lkvkubpjoe .gt_asterisk {
  font-size: 100%;
  vertical-align: 0;
}

#lkvkubpjoe .gt_indent_1 {
  text-indent: 5px;
}

#lkvkubpjoe .gt_indent_2 {
  text-indent: 10px;
}

#lkvkubpjoe .gt_indent_3 {
  text-indent: 15px;
}

#lkvkubpjoe .gt_indent_4 {
  text-indent: 20px;
}

#lkvkubpjoe .gt_indent_5 {
  text-indent: 25px;
}

#lkvkubpjoe .katex-display {
  display: inline-flex !important;
  margin-bottom: 0.75em !important;
}

#lkvkubpjoe div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {
  height: 0px !important;
}
</style>

<table class="gt_table caption-top table table-sm table-striped small" data-quarto-bootstrap="false">
<caption><strong>Hazard ratios for death</strong></caption>
<colgroup>
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
</colgroup>
<thead>
<tr class="gt_col_headings header">
<th id="label" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col"><strong>Characteristic</strong></th>
<th id="estimate" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>HR</strong></th>
<th id="conf.low" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>95% CI</strong></th>
<th id="p.value" class="gt_col_heading gt_columns_bottom_border gt_center" data-quarto-table-cell-role="th" scope="col"><strong>p-value</strong></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr class="odd">
<td class="gt_row gt_left" headers="label">Chemotherapy Treatment</td>
<td class="gt_row gt_center" headers="estimate"><br>
</td>
<td class="gt_row gt_center" headers="conf.low"><br>
</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;Drug A</td>
<td class="gt_row gt_center" headers="estimate">—</td>
<td class="gt_row gt_center" headers="conf.low">—</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;Drug B</td>
<td class="gt_row gt_center" headers="estimate">1.30</td>
<td class="gt_row gt_center" headers="conf.low">0.88, 1.92</td>
<td class="gt_row gt_center" headers="p.value">0.2</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">Age</td>
<td class="gt_row gt_center" headers="estimate">1.01</td>
<td class="gt_row gt_center" headers="conf.low">0.99, 1.02</td>
<td class="gt_row gt_center" headers="p.value">0.3</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">Grade</td>
<td class="gt_row gt_center" headers="estimate"><br>
</td>
<td class="gt_row gt_center" headers="conf.low"><br>
</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;I</td>
<td class="gt_row gt_center" headers="estimate">—</td>
<td class="gt_row gt_center" headers="conf.low">—</td>
<td class="gt_row gt_center" headers="p.value"><br>
</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;II</td>
<td class="gt_row gt_center" headers="estimate">1.21</td>
<td class="gt_row gt_center" headers="conf.low">0.73, 1.99</td>
<td class="gt_row gt_center" headers="p.value">0.5</td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="label">&nbsp;&nbsp;&nbsp;&nbsp;III</td>
<td class="gt_row gt_center" headers="estimate">1.79</td>
<td class="gt_row gt_center" headers="conf.low">1.12, 2.86</td>
<td class="gt_row gt_center" headers="p.value" style="font-weight: bold">0.014</td>
</tr>
</tbody><tfoot>
<tr class="gt_sourcenotes odd">
<td colspan="4" class="gt_sourcenote">Abbreviations: CI = Confidence Interval, HR = Hazard Ratio</td>
</tr>
</tfoot>

</table>

</div>
</div>
</div>
<p>A hazard ratio above 1 means a higher instantaneous risk; below 1, lower. <code>exponentiate = TRUE</code> converts the model’s log-hazard coefficients into the hazard ratios you actually report.</p>
</section>
<section id="now-check-proportional-hazards" class="level2">
<h2 class="anchored" data-anchor-id="now-check-proportional-hazards">Now check proportional hazards</h2>
<p>This is the step that separates a defensible analysis from a fragile one. <code>cox.zph()</code> tests whether each effect is stable over time:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">zph <span class="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>(cx)</span>
<span id="cb2-2">zph</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>       chisq df    p
trt    2.053  1 0.15
age    0.163  1 0.69
grade  4.365  2 0.11
GLOBAL 6.666  4 0.15</code></pre>
</div>
</div>
<p>Large p-values (and a non-significant <code>GLOBAL</code> row) mean the proportional-hazards assumption is reasonable. Back it up visually — the scaled Schoenfeld residuals should scatter flat around zero, with no trend:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><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;">3</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mar =</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;">4</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 class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>)</span>
<span id="cb4-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(zph, <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;">"#2f6fed"</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></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-coxzph" class="quarto-float quarto-figure quarto-figure-center anchored" width="768">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-coxzph-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/cox-proportional-hazards-r_files/figure-html/fig-coxzph-1.png" id="fig-coxzph" class="img-fluid figure-img" width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-coxzph-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="when-the-assumption-fails" class="level2">
<h2 class="anchored" data-anchor-id="when-the-assumption-fails">When the assumption fails</h2>
<p>A significant test isn’t the end of the world — it’s a signpost. The usual responses: <strong>stratify</strong> on the offending variable, fit a <strong>time-varying coefficient</strong>, split follow-up into time intervals, or switch to an accelerated failure-time model. What you should never do is report the hazard ratio as if the assumption held when it didn’t.</p>
</section>
<section id="the-takeaway" class="level2">
<h2 class="anchored" data-anchor-id="the-takeaway">The takeaway</h2>
<p>Fitting the Cox model is one line; earning the right to interpret it is the second line, <code>cox.zph()</code>. Report both, and your reviewers have one fewer thing to worry about.</p>
<hr>
<p><em>Pair this with <a href="../posts/kaplan-meier-ggplot2.html">Kaplan–Meier curves</a> and the rest of the <a href="../clinical-r.html">Clinical R toolkit</a>.</em></p>


</section>

 ]]></description>
  <category>clinical</category>
  <category>biostatistics</category>
  <category>survival</category>
  <guid>https://rverseanalytics.com/posts/cox-proportional-hazards-r.html</guid>
  <pubDate>Mon, 29 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>One-way ANOVA in R with post-hoc tests</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/one-way-anova-r-posthoc.html</link>
  <description><![CDATA[ 




<p>ANOVA tells you whether <em>any</em> group differs; a post-hoc test tells you <em>which</em>. Do the second step properly and you avoid inflating your false-positive rate. (For when to use ANOVA at all, see <a href="../posts/t-test-vs-anova.html">t-test vs ANOVA</a>.)</p>
<section id="step-1-the-anova" class="level2">
<h2 class="anchored" data-anchor-id="step-1-the-anova">Step 1: the ANOVA</h2>
<p>We’ll use the built-in <code>PlantGrowth</code> data — plant yields under a control and two treatments:</p>
<div class="cell">
<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">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;">aov</span>(weight <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> PlantGrowth)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(fit)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>            Df Sum Sq Mean Sq F value Pr(&gt;F)  
group        2  3.766  1.8832   4.846 0.0159 *
Residuals   27 10.492  0.3886                 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1</code></pre>
</div>
</div>
<p>A small p-value for <code>group</code> says the groups are not all equal — but not which pair drives it.</p>
</section>
<section id="step-2-tukeys-hsd" class="level2">
<h2 class="anchored" data-anchor-id="step-2-tukeys-hsd">Step 2: Tukey’s HSD</h2>
<p>Never just run a bunch of t-tests here. <strong>Tukey’s Honest Significant Difference</strong> compares every pair while controlling the family-wise error rate:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TukeyHSD</span>(fit)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = weight ~ group, data = PlantGrowth)

$group
            diff        lwr       upr     p adj
trt1-ctrl -0.371 -1.0622161 0.3202161 0.3908711
trt2-ctrl  0.494 -0.1972161 1.1852161 0.1979960
trt2-trt1  0.865  0.1737839 1.5562161 0.0120064</code></pre>
</div>
</div>
<p>Each row is a pairwise difference with an adjusted confidence interval and p-value. Any interval that excludes zero is a significant difference.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><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;">mar =</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;">8</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;">1</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>)</span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TukeyHSD</span>(fit), <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;">"#2f6fed"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-tukey" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-tukey-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/one-way-anova-r-posthoc_files/figure-html/fig-tukey-1.png" id="fig-tukey" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-tukey-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>Intervals crossing the dashed zero line are not significant; those entirely to one side are.</p>
</section>
<section id="before-you-trust-it" class="level2">
<h2 class="anchored" data-anchor-id="before-you-trust-it">Before you trust it</h2>
<p>ANOVA assumes roughly normal residuals and similar variances across groups. Check the residuals (<code>plot(fit)</code>) and <a href="../posts/checking-normality-r.html">normality</a>; if variances differ badly, use <code>oneway.test()</code> (Welch) instead, and if normality fails, the Kruskal–Wallis test.</p>
<hr>
<p><em>Running group comparisons in your data? <a href="../services.html">We’ll handle the assumptions and the write-up.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>anova</category>
  <category>r-tutorial</category>
  <guid>https://rverseanalytics.com/posts/one-way-anova-r-posthoc.html</guid>
  <pubDate>Sat, 27 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Power analysis before data collection — in base R</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/power-analysis-before-data.html</link>
  <description><![CDATA[ 




<p>The most expensive statistical mistake is made before any data exist: recruiting too few participants to detect the effect you care about. The fix costs ten lines of base R — no add-on packages, no point-and-click software.</p>
<section id="the-one-liner" class="level2">
<h2 class="anchored" data-anchor-id="the-one-liner">The one-liner</h2>
<p>Suppose we plan a two-group trial and consider a standardized difference of <em>d</em> = 0.5 (a “medium” effect) clinically meaningful. How many participants per group for 80% power at α = .05?</p>
<div class="cell">
<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;">power.t.test</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">delta =</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;">sd =</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;">sig.level =</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;">power =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.80</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
     Two-sample t test power calculation 

              n = 63.76576
          delta = 0.5
             sd = 1
      sig.level = 0.05
          power = 0.8
    alternative = two.sided

NOTE: n is number in *each* group</code></pre>
</div>
</div>
<p>About <strong>64 per group</strong>. The same function inverts in any direction — fix <code>n</code> and it returns the power, fix <code>power</code> and <code>n</code> and it returns the smallest detectable effect.</p>
</section>
<section id="the-more-honest-answer-a-power-curve" class="level2">
<h2 class="anchored" data-anchor-id="the-more-honest-answer-a-power-curve">The more honest answer: a power curve</h2>
<p>A single number hides how sensitive the design is to your effect-size guess. A curve makes the trade-off visible:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb3-2"></span>
<span id="cb3-3">grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expand.grid</span>(</span>
<span id="cb3-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</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;">150</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb3-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>)</span>
<span id="cb3-6">)</span>
<span id="cb3-7">grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>power <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mapply</span>(</span>
<span id="cb3-8">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(n, d) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">power.t.test</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;">delta =</span> d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>power,</span>
<span id="cb3-9">  grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n, grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>d</span>
<span id="cb3-10">)</span>
<span id="cb3-11"></span>
<span id="cb3-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(grid, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(n, power, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(d))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.80</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(</span>
<span id="cb3-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>),</span>
<span id="cb3-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d = 0.3 (small)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d = 0.5 (medium)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d = 0.8 (large)"</span>)</span>
<span id="cb3-18">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>percent) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb3-21">    <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;">"Power curves for a two-group t-test"</span>,</span>
<span id="cb3-22">    <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;">"Dashed line marks the conventional 80% target"</span>,</span>
<span id="cb3-23">    <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;">"Participants per group"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Statistical power"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span></span>
<span id="cb3-24">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-25">  <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="cb3-26">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb3-27">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-power-curve" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-power-curve-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/power-analysis-before-data_files/figure-html/fig-power-curve-1.png" id="fig-power-curve" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-power-curve-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>The curve tells the real story: if the true effect is small (<em>d</em> = 0.3), even 150 per group leaves you underpowered — and if the budget only allows 30 per group, you are implicitly betting on a large effect.</p>
</section>
<section id="beyond-the-t-test" class="level2">
<h2 class="anchored" data-anchor-id="beyond-the-t-test">Beyond the t-test</h2>
<p>Base R also ships <code>power.prop.test()</code> for two proportions and <code>power.anova.test()</code> for one-way ANOVA. For more complex designs — mixed models, survival endpoints, cluster randomization — the honest tool is <strong>simulation</strong>: generate data under your assumed model a few thousand times and count how often the analysis detects the effect. That is a topic for a future post.</p>
<p><em>Planning a study and unsure about the numbers? <a href="../contact.html">We do this for a living.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>study-design</category>
  <guid>https://rverseanalytics.com/posts/power-analysis-before-data.html</guid>
  <pubDate>Wed, 24 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Checking normality in R: Shapiro–Wilk and Q–Q plots</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/checking-normality-r.html</link>
  <description><![CDATA[ 




<p>Many common tests assume roughly normal data (or normal residuals). Here’s how to check that assumption in R without over-relying on any single number. This is exactly the judgement call behind question 5 of our <a href="../which-test.html">which-test tool</a>.</p>
<section id="two-tools-used-together" class="level2">
<h2 class="anchored" data-anchor-id="two-tools-used-together">Two tools, used together</h2>
<ul>
<li><strong>Shapiro–Wilk test</strong> (<code>shapiro.test</code>) — a formal test of the null “the data are normal.”</li>
<li><strong>Q–Q plot</strong> (<code>qqnorm</code> + <code>qqline</code>) — a visual check: normal data hug the diagonal line.</li>
</ul>
<p>Use both, and trust the plot when they seem to disagree.</p>
<div class="cell">
<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;">5</span>)</span>
<span id="cb1-2">x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span>, <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;">10</span>, <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>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">shapiro.test</span>(x)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
    Shapiro-Wilk normality test

data:  x
W = 0.98151, p-value = 0.3009</code></pre>
</div>
<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;">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 class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mar =</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;">4</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 class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>)</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hist</span>(x, <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;">"#2f6fed33"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">border =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</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;">"Histogram"</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;">"x"</span>)</span>
<span id="cb3-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qqnorm</span>(x, <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;">"#17a2b8"</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;">main =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Normal Q-Q plot"</span>)</span>
<span id="cb3-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qqline</span>(x, <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;">"#b02a37"</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></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-norm" class="quarto-float quarto-figure quarto-figure-center anchored" width="768">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-norm-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/checking-normality-r_files/figure-html/fig-norm-1.png" id="fig-norm" class="img-fluid figure-img" width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-norm-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>Points close to the red line and a bell-shaped histogram: normality is a reasonable assumption here.</p>
</section>
<section id="the-big-caveat-sample-size" class="level2">
<h2 class="anchored" data-anchor-id="the-big-caveat-sample-size">The big caveat: sample size</h2>
<p>The Shapiro–Wilk test is <strong>sensitive to sample size</strong>. In small samples it can miss real non-normality; in very large samples it flags trivial, harmless departures as “significant.” So:</p>
<ul>
<li><strong>Large n:</strong> a significant Shapiro–Wilk often doesn’t matter — the test you’re running is robust, and the Q–Q plot looks fine. Don’t panic over the p-value.</li>
<li><strong>Small n:</strong> the test has little power, so lean on the Q–Q plot and subject-matter knowledge.</li>
</ul>
</section>
<section id="if-its-not-normal" class="level2">
<h2 class="anchored" data-anchor-id="if-its-not-normal">If it’s not normal</h2>
<p>You have good options: a <strong>nonparametric</strong> test (Mann–Whitney, Kruskal–Wallis), a <strong>transformation</strong> (log, square-root), or a method that doesn’t need normality of the raw data. For regression, remember it’s the <strong>residuals</strong> that should be normal, not the predictors.</p>
<hr>
<p><em>Assumption checks are where analyses quietly go wrong. <a href="../services.html">We make them explicit.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>assumptions</category>
  <category>r-tutorial</category>
  <guid>https://rverseanalytics.com/posts/checking-normality-r.html</guid>
  <pubDate>Tue, 23 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Analysing energy consumption time series in R</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/energy-consumption-time-series-r.html</link>
  <description><![CDATA[ 




<p>Electricity and utility metering produces exactly the kind of data R was built for: a long, regular time series with a trend, repeating seasonal patterns and noise all tangled together. Pulling those apart is the first step toward forecasting demand, spotting anomalies and sizing tariffs. Here’s the core workflow on a simulated daily-load series.</p>
<section id="a-realistic-load-series" class="level2">
<h2 class="anchored" data-anchor-id="a-realistic-load-series">A realistic load series</h2>
<p>We’ll simulate two years of daily consumption with an annual heating/cooling cycle, a weekday-vs-weekend pattern, a gentle upward trend and random noise — the ingredients of real metering data:</p>
<div class="cell">
<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;">library</span>(ggplot2)</span>
<span id="cb1-2"></span>
<span id="cb1-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;">42</span>)</span>
<span id="cb1-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;">730</span></span>
<span id="cb1-5">day <span class="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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2024-01-01"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"day"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> n)</span>
<span id="cb1-6">t   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n)</span>
<span id="cb1-7">wday <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(day, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%u"</span>))          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1 = Mon … 7 = Sun</span></span>
<span id="cb1-8"></span>
<span id="cb1-9">annual  <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;">20</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;">cos</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="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> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">365</span>)           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># seasonal heating/cooling</span></span>
<span id="cb1-10">weekend <span class="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>(wday <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;">6</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># weekends draw less</span></span>
<span id="cb1-11">trend   <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.015</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> t                            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># slow growth</span></span>
<span id="cb1-12">load    <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;">130</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> annual <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> weekend <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> trend <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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb1-13"></span>
<span id="cb1-14">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(day, load)</span>
<span id="cb1-15"></span>
<span id="cb1-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(d, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(day, load)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Simulated daily electricity load"</span>,</span>
<span id="cb1-19">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Load (MWh)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-load" class="quarto-float quarto-figure quarto-figure-center anchored" width="768">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-load-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/energy-consumption-time-series-r_files/figure-html/fig-load-1.png" id="fig-load" class="img-fluid figure-img" width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-load-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="decompose-it-trend-season-remainder" class="level2">
<h2 class="anchored" data-anchor-id="decompose-it-trend-season-remainder">Decompose it: trend + season + remainder</h2>
<p><code>stl()</code> (seasonal-trend decomposition using loess) splits the series into interpretable components. With a weekly period it isolates the Monday-to-Sunday cycle and leaves the annual swing in the trend:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">ts_load <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ts</span>(load, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">frequency =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>)</span>
<span id="cb2-2">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;">stl</span>(ts_load, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s.window =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"periodic"</span>)</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(fit, <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;">"#1b2a4a"</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;">"STL decomposition of daily load"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-stl" class="quarto-float quarto-figure quarto-figure-center anchored" width="768">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-stl-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/energy-consumption-time-series-r_files/figure-html/fig-stl-1.png" id="fig-stl" class="img-fluid figure-img" width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-stl-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2
</figcaption>
</figure>
</div>
</div>
</div>
<p>Each panel is a story: the <strong>trend</strong> shows underlying growth and the seasonal swing, the <strong>seasonal</strong> panel is the repeating weekly shape, and the <strong>remainder</strong> is what’s left — where anomalies and one-off events show up.</p>
</section>
<section id="read-the-weekday-profile" class="level2">
<h2 class="anchored" data-anchor-id="read-the-weekday-profile">Read the weekday profile</h2>
<p>Aggregate straight from the data to get the average load by day of week — the “load profile” utilities plan around:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">labs_wday <span class="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;">"Mon"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tue"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Thu"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fri"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sat"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sun"</span>)</span>
<span id="cb3-2">prof <span class="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>(load <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> wday, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(load, wday), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">FUN =</span> mean)</span>
<span id="cb3-3">prof<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>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;">factor</span>(labs_wday[prof<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>wday], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> labs_wday)</span>
<span id="cb3-4"></span>
<span id="cb3-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(prof, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(label, load)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_col</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Average load by day of week"</span>,</span>
<span id="cb3-8">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean load (MWh)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-profile" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-profile-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/energy-consumption-time-series-r_files/figure-html/fig-profile-1.png" id="fig-profile" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-profile-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3
</figcaption>
</figure>
</div>
</div>
</div>
<p>The weekend drop is unmistakable — and once it’s quantified, it feeds directly into forecasting and capacity planning.</p>
</section>
<section id="where-this-goes-next" class="level2">
<h2 class="anchored" data-anchor-id="where-this-goes-next">Where this goes next</h2>
<p>Decomposition is the foundation; from here the same data supports forecasting (<code>forecast</code>, <code>prophet</code>, or a seasonal ARIMA), anomaly detection on the remainder, and interactive dashboards that let operations teams explore load themselves. That last step is squarely our <a href="../services.html">Shiny practice</a>, and the energy sector is one of the <a href="../industries.html">industries we serve</a>.</p>
<hr>
<p><em>Have meter or market data that needs turning into decisions? <a href="../contact.html">Tell us about it.</a></em></p>


</section>

 ]]></description>
  <category>energy</category>
  <category>time-series</category>
  <category>forecasting</category>
  <guid>https://rverseanalytics.com/posts/energy-consumption-time-series-r.html</guid>
  <pubDate>Sun, 21 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>t-test vs ANOVA: when to use which (with R)</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/t-test-vs-anova.html</link>
  <description><![CDATA[ 




<p>They feel like different tools, but a t-test and one-way ANOVA are the same idea at different scales. Knowing the relationship keeps you from a classic mistake. (Not sure which test fits your design? Try our <a href="../which-test.html">which-test tool</a>.)</p>
<section id="the-rule" class="level2">
<h2 class="anchored" data-anchor-id="the-rule">The rule</h2>
<ul>
<li><strong>Two groups</strong> → two-sample <em>t</em>-test.</li>
<li><strong>Three or more groups</strong> → one-way ANOVA.</li>
</ul>
</section>
<section id="they-agree-for-two-groups" class="level2">
<h2 class="anchored" data-anchor-id="they-agree-for-two-groups">They agree for two groups</h2>
<p>For exactly two groups, ANOVA’s <em>F</em> equals the <em>t</em> statistic squared — same p-value, same conclusion:</p>
<div class="cell">
<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;">10</span>)</span>
<span id="cb1-2">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;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>))</span>
<span id="cb1-3">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</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;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>))</span>
<span id="cb1-4"></span>
<span id="cb1-5">t_res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t.test</span>(y <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;">var.equal =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-6">a_res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aov</span>(y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> g))</span>
<span id="cb1-7"></span>
<span id="cb1-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">t_squared =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(t_res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb1-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">F_value   =</span> a_res[[<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;">"F value"</span>]][<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>t_squared   F_value 
 12.58062  12.58062 </code></pre>
</div>
</div>
<p>The two numbers match — a t-test is just ANOVA with two groups.</p>
</section>
<section id="why-not-many-t-tests" class="level2">
<h2 class="anchored" data-anchor-id="why-not-many-t-tests">Why not many t-tests?</h2>
<p>With three groups you might be tempted to run A-vs-B, A-vs-C, B-vs-C. Don’t: each test carries a 5% false-positive risk, so three tests push your overall error rate well above 5%. ANOVA asks “is there <strong>any</strong> difference?” in a single test at the right error rate.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(PlantGrowth, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(group, weight, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> group)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_boxplot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.legend =</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>
<span id="cb3-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5aa0ff"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"One-way ANOVA compares 3+ groups at once"</span>,</span>
<span id="cb3-6">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Weight"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-anova" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-anova-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/t-test-vs-anova_files/figure-html/fig-anova-1.png" id="fig-anova" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-anova-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="after-a-significant-anova" class="level2">
<h2 class="anchored" data-anchor-id="after-a-significant-anova">After a significant ANOVA</h2>
<p>ANOVA tells you <em>a</em> difference exists, not <em>which</em>. Follow up with a post-hoc test that controls for multiple comparisons — see <a href="../posts/one-way-anova-r-posthoc.html">one-way ANOVA with post-hoc tests in R</a>.</p>
<hr>
<p><em>Comparing groups in your own data? <a href="../services.html">We’ll pick the right test and defend it.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>hypothesis-testing</category>
  <category>anova</category>
  <guid>https://rverseanalytics.com/posts/t-test-vs-anova.html</guid>
  <pubDate>Fri, 19 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>One template, fifty reports: parameterised Quarto in practice</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/parameterized-quarto-reports.html</link>
  <description><![CDATA[ 




<p>A pattern that pays for itself on almost every reporting project: write <strong>one</strong> Quarto document, declare its inputs as parameters, and render it once per site, clinic, region or client.</p>
<section id="declare-the-parameters" class="level2">
<h2 class="anchored" data-anchor-id="declare-the-parameters">Declare the parameters</h2>
<p>In the report’s YAML header:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb1-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">title</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Monthly Quality Report — `r params$site`"</span></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> docx</span></span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">params</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">site</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Site A"</span></span>
<span id="cb1-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">month</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2026-06"</span></span>
<span id="cb1-7"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
<p>Inside the document, <code>params$site</code> and <code>params$month</code> drive the filtering:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">monthly <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> readr<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;">read_csv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data/measurements.csv"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-2">  dplyr<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;">filter</span>(site <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> params<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>site,</span>
<span id="cb2-3">                <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(date, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%Y-%m"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> params<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>month)</span></code></pre></div></div>
</div>
</section>
<section id="render-the-batch" class="level2">
<h2 class="anchored" data-anchor-id="render-the-batch">Render the batch</h2>
<p>One small driver script produces the whole set:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">sites <span class="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;">"Site A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Site B"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Site C"</span>)</span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (s <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sites) {</span>
<span id="cb3-4">  quarto<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;">quarto_render</span>(</span>
<span id="cb3-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"monthly_report.qmd"</span>,</span>
<span id="cb3-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">execute_params =</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;">site =</span> s, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">month =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2026-06"</span>),</span>
<span id="cb3-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">output_file =</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;">"report_"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gsub</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" "</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_"</span>, s), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_2026-06.docx"</span>)</span>
<span id="cb3-8">  )</span>
<span id="cb3-9">}</span></code></pre></div></div>
</div>
<p>Fifty sites is the same loop with a longer vector.</p>
</section>
<section id="why-this-beats-copy-paste" class="level2">
<h2 class="anchored" data-anchor-id="why-this-beats-copy-paste">Why this beats copy-paste</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb4-2"></span>
<span id="cb4-3">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>
<span id="cb4-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_reports =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb4-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach  =</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;">"Manual copy-paste"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Parameterised Quarto"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>)</span>
<span id="cb4-6">)</span>
<span id="cb4-7">d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hours <span class="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>(d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>approach <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;">"Manual copy-paste"</span>,</span>
<span id="cb4-8">                  d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_reports <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 class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ~1.5 h per hand-edited report</span></span>
<span id="cb4-9">                  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_reports <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.02</span>)     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one-time template + render time</span></span>
<span id="cb4-10"></span>
<span id="cb4-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(d, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(n_reports, hours, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> approach)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb4-15">    <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;">"Cumulative effort: hand-edited vs. parameterised reports"</span>,</span>
<span id="cb4-16">    <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;">"Illustrative estimates — the template costs more up front, then almost nothing"</span>,</span>
<span id="cb4-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of reports"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hours of analyst time"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span></span>
<span id="cb4-18">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb4-21">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-effort" class="quarto-float quarto-figure quarto-figure-center anchored" width="672">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-effort-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/parameterized-quarto-reports_files/figure-html/fig-effort-1.png" id="fig-effort" class="img-fluid figure-img" width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-effort-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>Beyond the hours, the real win is <strong>consistency</strong>: every report is generated from the same logic, so a fix or improvement lands in all fifty at the next render — and none of them can silently drift out of sync with the data.</p>


</section>

 ]]></description>
  <category>quarto</category>
  <category>reporting</category>
  <category>workflow</category>
  <guid>https://rverseanalytics.com/posts/parameterized-quarto-reports.html</guid>
  <pubDate>Wed, 17 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Pearson vs Spearman correlation: which one, and when (in R)</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/pearson-vs-spearman-correlation.html</link>
  <description><![CDATA[ 




<p>Both quantify how two variables move together, but they answer subtly different questions. Choosing wrong can hide a strong relationship or overstate a fragile one. (Want a quick number and scatter plot? Use our <a href="../tools/correlation-calculator.html">correlation calculator</a>.)</p>
<section id="the-difference-in-one-sentence" class="level2">
<h2 class="anchored" data-anchor-id="the-difference-in-one-sentence">The difference in one sentence</h2>
<ul>
<li><strong>Pearson</strong> measures the strength of a <strong>linear</strong> relationship, using the raw values.</li>
<li><strong>Spearman</strong> measures the strength of a <strong>monotonic</strong> relationship, using the <em>ranks</em> — so it captures “as X goes up, Y goes up” even when the shape is curved, and it shrugs off outliers.</li>
</ul>
</section>
<section id="where-they-disagree" class="level2">
<h2 class="anchored" data-anchor-id="where-they-disagree">Where they disagree</h2>
<p>Take a strong but curved (exponential) relationship:</p>
<div class="cell">
<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;">library</span>(ggplot2)</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;">3</span>)</span>
<span id="cb1-3">x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">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;">60</span></span>
<span id="cb1-4">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</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;">18</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>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</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>
<span id="cb1-5"></span>
<span id="cb1-6">pear <span class="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>(x, y)                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pearson</span></span>
<span id="cb1-7">spear <span class="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>(x, y, <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;">"spearman"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Spearman</span></span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(x, y), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(x, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</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;">"Pearson r = %.2f   vs   Spearman rho = %.2f"</span>, pear, spear),</span>
<span id="cb1-12">       <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;">"X"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Y"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-corr" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-corr-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/pearson-vs-spearman-correlation_files/figure-html/fig-corr-1.png" id="fig-corr" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-corr-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>The relationship is essentially perfect and increasing, so Spearman is near 1. Pearson is lower because the relationship isn’t a straight line — it’s penalised for the curvature.</p>
</section>
<section id="getting-the-test" class="level2">
<h2 class="anchored" data-anchor-id="getting-the-test">Getting the test</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor.test</span>(x, y, <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;">"spearman"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
    Spearman's rank correlation rho

data:  x and y
S = 2214, p-value &lt; 2.2e-16
alternative hypothesis: true rho is not equal to 0
sample estimates:
      rho 
0.9384829 </code></pre>
</div>
</div>
<p><code>cor.test()</code> gives the coefficient, the test statistic and a p-value for either method.</p>
</section>
<section id="how-to-choose" class="level2">
<h2 class="anchored" data-anchor-id="how-to-choose">How to choose</h2>
<ul>
<li><strong>Pearson</strong> when the relationship looks linear and the data are roughly normal without wild outliers.</li>
<li><strong>Spearman</strong> when the relationship is monotonic but curved, the data are ordinal, or outliers/skew are present.</li>
</ul>
<p>Always <strong>plot first</strong> — a coefficient without a scatter plot hides curvature and outliers. And whichever you use: correlation is not causation.</p>
<hr>
<p><em>Correlation is usually the opening question. For regression, confounder adjustment and a write-up, <a href="../services.html">that’s our work.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>correlation</category>
  <category>r-tutorial</category>
  <guid>https://rverseanalytics.com/posts/pearson-vs-spearman-correlation.html</guid>
  <pubDate>Sun, 14 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Confidence intervals explained, with an R simulation</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/confidence-intervals-explained-r.html</link>
  <description><![CDATA[ 




<p>A confidence interval says more than a p-value: it shows the range of plausible values and how precisely you’ve estimated them. But the “95%” is almost always misread. Let’s fix that with a simulation. (Just need an interval? Use our <a href="../tools/confidence-interval-calculator.html">confidence interval calculator</a>.)</p>
<section id="what-95-actually-means" class="level2">
<h2 class="anchored" data-anchor-id="what-95-actually-means">What 95% actually means</h2>
<p>A 95% CI is built by a <em>procedure</em> that, across many repeated samples, produces intervals capturing the true value 95% of the time. It is <strong>not</strong> a 95% probability that the truth lies in <em>this particular</em> interval — once computed, the interval either contains the true value or it doesn’t.</p>
</section>
<section id="watch-it-work" class="level2">
<h2 class="anchored" data-anchor-id="watch-it-work">Watch it work</h2>
<p>Draw 100 samples from a population with a known mean of 50, build a 95% CI from each, and colour the ones that miss:</p>
<div class="cell">
<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;">library</span>(ggplot2)</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;">7</span>)</span>
<span id="cb1-3">sims <span class="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;">replicate</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, {</span>
<span id="cb1-4">  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;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <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;">50</span>, <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;">10</span>)</span>
<span id="cb1-5">  <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.test</span>(x)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conf.int)</span>
<span id="cb1-6">}))</span>
<span id="cb1-7">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">study =</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;">100</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lo =</span> sims[,<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;">hi =</span> sims[,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb1-8">d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>miss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lo <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;">50</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hi <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;">50</span></span>
<span id="cb1-9"></span>
<span id="cb1-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(d, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(study, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymin =</span> lo, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymax =</span> hi, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> miss)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_linerange</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</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;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FALSE"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TRUE"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b02a37"</span>),</span>
<span id="cb1-14">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">guide =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</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;">"Of 100 intervals, "</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>miss), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" missed the true mean"</span>),</span>
<span id="cb1-16">       <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;">"Sample number"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Estimated mean"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-ci" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-ci-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/confidence-intervals-explained-r_files/figure-html/fig-ci-1.png" id="fig-ci" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-ci-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>Close to 5 in 100 miss — that’s the 95% procedure behaving exactly as designed.</p>
</section>
<section id="computing-them" class="level2">
<h2 class="anchored" data-anchor-id="computing-them">Computing them</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">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;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t.test</span>(x)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conf.int          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># mean, t-based</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 45.57248 54.44697
attr(,"conf.level")
[1] 0.95</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">prop.test</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conf.int  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># proportion (Wilson-style)</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.6585632 0.8949784
attr(,"conf.level")
[1] 0.95</code></pre>
</div>
</div>
<p>For proportions, prefer the <strong>Wilson</strong> interval over the textbook Wald formula — it behaves far better for small samples and extreme proportions.</p>
</section>
<section id="why-report-them" class="level2">
<h2 class="anchored" data-anchor-id="why-report-them">Why report them</h2>
<p>A CI answers “how big, and how sure?” in one line — far more useful than a bare p-value. Wide interval, more uncertainty; narrow, more precision.</p>
<hr>
<p><em>Intervals are only as good as their assumptions. <a href="../services.html">Checking those is our job.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>confidence-intervals</category>
  <category>estimation</category>
  <guid>https://rverseanalytics.com/posts/confidence-intervals-explained-r.html</guid>
  <pubDate>Thu, 11 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>How to interpret a p-value (correctly), with R</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/interpreting-p-values.html</link>
  <description><![CDATA[ 




<p>Few numbers are as widely reported and as widely misunderstood as the p-value. Here’s the correct definition, the common traps, and a short R simulation that makes the idea click. (Have a test statistic already? Convert it with our <a href="../tools/p-value-calculator.html">p-value calculator</a>.)</p>
<section id="the-definition" class="level2">
<h2 class="anchored" data-anchor-id="the-definition">The definition</h2>
<blockquote class="blockquote">
<p>The p-value is the probability of observing data at least as extreme as yours, <strong>assuming the null hypothesis is true.</strong></p>
</blockquote>
<p>Small p → your data would be surprising if there were no effect → evidence against the null. That’s it. It is <strong>not</strong> the probability that the null is true, and it says nothing about how <em>big</em> or <em>important</em> an effect is.</p>
</section>
<section id="the-simulation-that-makes-it-click" class="level2">
<h2 class="anchored" data-anchor-id="the-simulation-that-makes-it-click">The simulation that makes it click</h2>
<p>If the null hypothesis is true, p-values are <strong>uniformly distributed</strong> between 0 and 1. Let’s see it — run 5,000 t-tests on data with no real difference:</p>
<div class="cell">
<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;">library</span>(ggplot2)</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">pvals <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t.test</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value)</span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(pvals), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(pvals)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_histogram</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>,</span>
<span id="cb1-7">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</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.85</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</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;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b02a37"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Under the null, p-values are uniform"</span>,</span>
<span id="cb1-10">       <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;">"5,000 t-tests on groups with no true difference"</span>,</span>
<span id="cb1-11">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p-value"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Count"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_family =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sans"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-null" class="quarto-float quarto-figure quarto-figure-center anchored" width="720">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-null-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/interpreting-p-values_files/figure-html/fig-null-1.png" id="fig-null" class="img-fluid figure-img" width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-null-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<p>The bars are flat — every p-value is equally likely. And notice the leftmost bar: about 5% of tests give p &lt; 0.05 <strong>even though nothing is going on.</strong> That 5% <em>is</em> your false-positive rate, and it’s exactly why running many tests and keeping the “significant” ones is so dangerous.</p>
</section>
<section id="three-traps-to-avoid" class="level2">
<h2 class="anchored" data-anchor-id="three-traps-to-avoid">Three traps to avoid</h2>
<ul>
<li><strong>p is not effect size.</strong> With a big enough sample, a trivial difference becomes “significant.” Always report an <a href="../posts/cohens-d-effect-size-r.html">effect size</a> and a <a href="../posts/confidence-intervals-explained-r.html">confidence interval</a>.</li>
<li><strong>Non-significant ≠ no effect.</strong> It may just mean too little <a href="../posts/sample-size-calculation-r.html">power</a>.</li>
<li><strong>p-hacking is real.</strong> Deciding tests after seeing the data inflates false positives — pre-specify.</li>
</ul>
<hr>
<p><em>A p-value is one line in a larger story. Want the whole analysis done right? <a href="../services.html">We can help.</a></em></p>


</section>

 ]]></description>
  <category>statistics</category>
  <category>hypothesis-testing</category>
  <category>p-values</category>
  <guid>https://rverseanalytics.com/posts/interpreting-p-values.html</guid>
  <pubDate>Tue, 09 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Write your ggplot2 theme once, use it everywhere</title>
  <dc:creator>Rverse Analytics</dc:creator>
  <link>https://rverseanalytics.com/posts/one-ggplot-theme.html</link>
  <description><![CDATA[ 




<p>Open any report produced by a team without a shared plotting theme and you can tell which analyst made which figure — different fonts, different greys, different grid lines. The fix is a <strong>theme function</strong>: written once, applied everywhere, versioned like any other code.</p>
<section id="a-complete-theme-in-one-function" class="level2">
<h2 class="anchored" data-anchor-id="a-complete-theme-in-one-function">A complete theme in one function</h2>
<div class="cell">
<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;">library</span>(ggplot2)</span>
<span id="cb1-2"></span>
<span id="cb1-3">theme_rverse <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) {</span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> base_size) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb1-6">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>,</span>
<span id="cb1-7">                                <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rel</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.15</span>)),</span>
<span id="cb1-8">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.subtitle =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a6478"</span>,</span>
<span id="cb1-9">                                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">margin =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">margin</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;">10</span>)),</span>
<span id="cb1-10">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"plot"</span>,</span>
<span id="cb1-11">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>),</span>
<span id="cb1-12">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="cb1-13">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.major =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#e4e8f0"</span>),</span>
<span id="cb1-14">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb1-15">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">strip.text =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>)</span>
<span id="cb1-16">    )</span>
<span id="cb1-17">}</span>
<span id="cb1-18"></span>
<span id="cb1-19">scale_colour_rverse <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="cb1-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6fed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#17a2b8"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1b2a4a"</span>,</span>
<span id="cb1-21">                                 <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#e8590c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#6f42c1"</span>), ...)</span>
<span id="cb1-22">}</span></code></pre></div></div>
</div>
</section>
<section id="before-and-after" class="level2">
<h2 class="anchored" data-anchor-id="before-and-after">Before and after</h2>
<p>The same plot, the same code — the only difference is the final line.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">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;">ggplot</span>(iris, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(Sepal.Length, Petal.Length, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> Species)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb2-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb2-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Default ggplot2 look"</span>,</span>
<span id="cb2-4">       <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;">"Grey panel, default palette, top-left legend nowhere in particular"</span>,</span>
<span id="cb2-5">       <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;">"Sepal length (cm)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Petal length (cm)"</span>)</span>
<span id="cb2-6">p</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-theme-before" class="quarto-float quarto-figure quarto-figure-center anchored" width="672">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-theme-before-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/one-ggplot-theme_files/figure-html/fig-theme-before-1.png" id="fig-theme-before" class="img-fluid figure-img" width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-theme-before-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1
</figcaption>
</figure>
</div>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">p <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"With theme_rverse() and the brand palette"</span>,</span>
<span id="cb3-3">       <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;">"One added line — typography, grid and colours now match every other figure"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_rverse</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_rverse</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-theme-after" class="quarto-float quarto-figure quarto-figure-center anchored" width="672">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-theme-after-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://rverseanalytics.com/posts/one-ggplot-theme_files/figure-html/fig-theme-after-1.png" id="fig-theme-after" class="img-fluid figure-img" width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig quarto-uncaptioned" id="fig-theme-after-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="make-it-the-default" class="level2">
<h2 class="anchored" data-anchor-id="make-it-the-default">Make it the default</h2>
<p>The step most teams skip: you don’t have to add <code>+ theme_rverse()</code> to every plot. Set it once at the top of the script or in a package <code>.onLoad()</code>:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_set</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_rverse</span>())</span>
<span id="cb4-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">options</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ggplot2.discrete.colour =</span> scale_colour_rverse)</span></code></pre></div></div>
</div>
<p>From that line on, every ggplot in the session is on-brand by default — and when the brand changes, you update one function, re-render, and every figure in every report follows.</p>
</section>
<section id="where-to-keep-it" class="level2">
<h2 class="anchored" data-anchor-id="where-to-keep-it">Where to keep it</h2>
<ul>
<li><strong>One project?</strong> A <code>R/theme.R</code> file sourced at the top of the analysis.</li>
<li><strong>A team?</strong> An internal R package (<code>yourorg.theme</code>) — install once, <code>library()</code> everywhere. This is exactly the kind of small internal package we build in our <a href="../services.html">package development service</a>.</li>
</ul>


</section>

 ]]></description>
  <category>ggplot2</category>
  <category>workflow</category>
  <guid>https://rverseanalytics.com/posts/one-ggplot-theme.html</guid>
  <pubDate>Sun, 07 Jun 2026 21:00:00 GMT</pubDate>
</item>
</channel>
</rss>
