<?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>%&gt;% dreams</title>
<link>https://ivelasq.rbind.io/</link>
<atom:link href="https://ivelasq.rbind.io/index.xml" rel="self" type="application/rss+xml"/>
<description>Isabella Velásquez Personal Website</description>
<generator>quarto-1.8.27</generator>
<lastBuildDate>Tue, 27 May 2025 00:00:00 GMT</lastBuildDate>
<item>
  <title>Porting my favorite RStudio color theme to Positron</title>
  <link>https://ivelasq.rbind.io/blog/positron-theme/</link>
  <description><![CDATA[ 




<section id="my-favorite-rstudio-theme" class="level2">
<h2 class="anchored" data-anchor-id="my-favorite-rstudio-theme">My favorite RStudio theme</h2>
<p>My favorite color theme in RStudio is <a href="https://github.com/chriskempson/tomorrow-theme/blob/master/textmate/Tomorrow-Night-Bright.tmTheme">Tomorrow Night Bright</a>. It’s an excellent, dark, high-contrast (‘bright’) theme that I’ve used consistently since I first started using RStudio. Originally written by Chris Kempson as one of the variants included in the MIT-licensed <a href="https://github.com/chriskempson/tomorrow-theme">Tomorrow</a> theme series, it has been ported widely to many editors, and is included as a default color theme in RStudio.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/positron-theme/images/1-tnb_palette.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3); border-radius: 5px;"></p>
</figure>
</div>
<p>In this post, we will cover various color themes in <a href="https://positron.posit.co">Positron</a>, specifically how they are implemented in the <a href="https://code.visualstudio.com/docs/configure/custom-layout#_editor">editor</a> (i.e., syntax highlighting) and in other parts of the IDE (i.e., the <a href="https://code.visualstudio.com/docs/configure/custom-layout#_workbench">workbench</a> or <a href="https://en.m.wikipedia.org/wiki/Graphical_user_interface#GUI_and_interaction_design">chrome</a> around the editor). To do that, we need a great example script that shows off various R features. There’s plenty of good scripts out there, but this is a great opportunity to tell you, dear readers, about my new book and R package.</p>
<p>For the screenshots below, I’ll be using a script from <a href="https://tidy-survey-r.github.io/tidy-survey-book/">my new book</a> (co-written with Stephanie A. Zimmer and Rebecca J. Powell), which comes with an accompanying R package, <a href="https://tidy-survey-r.github.io/srvyrexploR">srvyexploR</a>. This package provides datasets and scripts to help readers follow along with examples and exercises. The <a href="https://github.com/tidy-survey-r/srvyrexploR/blob/main/data-raw/anes_2020.R">R script</a>, <code>anes_2020.R</code>, displays a wide breadth of symbols and colors. The screenshots below from RStudio and Positron should give you a flavor of the iterative changes we made in the Positron theme as we ported it from RStudio.</p>
<p>To start, here is what lines 347-366 of <code>anes_2020.R</code> look like in RStudio with the Tomorrow Night Bright theme:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/positron-theme/images/2-rstudio_tnb.png" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<p>Looks great, right?! That’s what I’ve been used to for many years now. Please note that I have <a href="https://posit.co/blog/rstudio-1-4-preview-rainbow-parentheses">rainbow parentheses</a> enabled in RStudio. Rainbow parentheses follow their own color palette, independent from the theme itself.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Fun fact
</div>
</div>
<div class="callout-body-container callout-body">
<p>After exploring RStudio’s source code, we were very excited to learn that the color palette for rainbow parentheses was <a href="https://github.com/rstudio/rstudio/blob/3bda5e5a379c033d21408d5393c9daa3176641b2/src/gwt/src/org/rstudio/core/client/theme/res/themeStyles.css#L2735-L2736">developed in R</a>!</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">colorspace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">swatchplot</span>(colorspace<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qualitative_hcl</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">palette =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"set2"</span>))</span></code></pre></div></div>
</div>
</div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/positron-theme/images/3-rainbow_parentheses.png" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
</section>
<section id="now-back-to-the-problem-at-hand" class="level2">
<h2 class="anchored" data-anchor-id="now-back-to-the-problem-at-hand">Now back to the problem at hand</h2>
<p>I, <a href="https://www.andrewheiss.com/blog/2024/07/08/fun-with-positron">like</a> <a href="https://bsky.app/profile/juliasilge.fosstodon.org.ap.brid.gy/post/3l7lkkdixeul2">many</a> <a href="https://bsky.app/profile/coatless.bsky.social/post/3kvxphnuinr2m">others</a>, am very excited about the early release of <a href="https://positron.posit.co/">Positron</a> and love seeing the community get their hands on it. As a Posit employee, I’ve had the chance to use it for many months. One of its biggest strengths is the <a href="https://open-vsx.org/extension/grrrck/positron-plus-1-e">Open VSX Registry</a> extension mechanism. It unlocks infinite customizability, just like in VS Code.</p>
<p>Being so attached to the Tomorrow Night Bright theme in RStudio, I quickly noticed that Positron includes <a href="https://github.com/posit-dev/positron/blob/main/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json">Tomorrow Night Blue</a> by default, but not my favorite theme. I tried out Microsoft’s <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.Theme-TomorrowKit">own</a> Tomorrow Night Bright <a href="https://open-vsx.org/extension/ms-vscode/Theme-TomorrowKit">extension</a>, but the colors felt off. It had an excessive amount of syntax highlighting and an especially distracting use of red. Here’s what the same lines of <code>anes_2020.R</code> look like using the Microsoft port of Tomorrow Night Bright in Positron:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/positron-theme/images/4-positron_ms_tnb.png" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<p>The Microsoft port of Tomorrow Night Bright had dated grey/blue workbench elements, reflecting its original design (released 2015, last updated 2017), rather than the style of more modern dark themes. Looking for other ‘bright’ themes, I found <a href="https://marketplace.visualstudio.com/items?itemName=GitHub.github-vscode-theme">GitHub Dark Default</a>, a sleek dark-and-bright theme with 16.3M installs in the VS Code Extension Marketplace and 156K in the <a href="https://open-vsx.org/extension/GitHub/github-vscode-theme">Open VSX Registry</a> as of this writing. It is featured in <a href="https://github.com/gadenbuie">Garrick Aden-Buie</a>‘s Positron Extension Pack, <a href="https://open-vsx.org/extension/grrrck/positron-plus-1-e">Positron +1e</a>. While very popular, GitHub Dark Default also suffers from excessive (’saturated’) syntax highlighting of R code in Positron:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/positron-theme/images/5-positron_gdd.png" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<p>With help from my <a href="https://github.com/gvelasq">brother</a>, I decided to write my own extension to better approximate what I’m used to in RStudio, and I’m pleased to announce that the resulting extension ‘Tomorrow Night Bright (R Classic)’ is now available on both the <a href="https://open-vsx.org/extension/gvelasq/tomorrow-night-bright-r-classic">Open VSX Registry</a> for Positron and the <a href="https://marketplace.visualstudio.com/items?itemName=gvelasq.tomorrow-night-bright-r-classic">VS Code Extension Marketplace</a> for VS Code!</p>
<p>Here is the final look:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/positron-theme/images/7-positron_tnb_r_classic.png" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<p>Let’s walk through porting this theme over to Positron.</p>
</section>
<section id="creating-a-vs-code-color-theme-extension" class="level2">
<h2 class="anchored" data-anchor-id="creating-a-vs-code-color-theme-extension">Creating a VS Code color theme extension</h2>
<section id="installing-the-required-software" class="level3">
<h3 class="anchored" data-anchor-id="installing-the-required-software">Installing the required software</h3>
<p>This tutorial assumes you already have <a href="https://posit.co/downloads/">RStudio</a> and <a href="https://positron.posit.co/download.html">Positron</a> installed. If not, do that first!<sup>1</sup></p>
<p>You’ll need a few different programs to create your first extension.</p>
<p>Install Git:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Install Homebrew (if you don't already have it on macOS)</span></span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/bin/bash</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-fsSL</span> https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Install Git after Homebrew is installed</span></span>
<span id="cb2-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install –-cask git</span></code></pre></div></div>
<p>Install <a href="https://nodejs.org/en/download">Node.js</a>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Download and install nvm:</span></span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o-</span> https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bash</span></span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Download and install Node.js:</span></span>
<span id="cb3-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">nvm</span> install 22</span></code></pre></div></div>
<p>Then, restart your terminal:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Verify the Node.js version:</span></span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">node</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-v</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Should print "v22.13.1".</span></span>
<span id="cb4-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">nvm</span> current <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Should print "v22.13.1".</span></span>
<span id="cb4-4"></span>
<span id="cb4-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Verify npm version:</span></span>
<span id="cb4-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">npm</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-v</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Should print "10.9.2".</span></span></code></pre></div></div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Note: Avoid using Homebrew for Node
</div>
</div>
<div class="callout-body-container callout-body">
<p>I played around with installing Node.js and, while possible to do with Homebrew with <code>brew install node@20</code>, this is quite time-consuming since Homebrew will install and then compile all of its dependencies from source. I was using an older laptop and <code>nvm</code> (as detailed in the steps above) worked great to install the Node.js binary.</p>
</div>
</div>
<p>Finally, install Yeoman:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">npm</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--global</span> yo generator-code</span></code></pre></div></div>
</section>
<section id="creating-the-extension" class="level3">
<h3 class="anchored" data-anchor-id="creating-the-extension">Creating the extension</h3>
<p>Now that everything is installed, let’s begin actually creating an extension. Point your terminal to your preferred folder:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> ~/rrr</span></code></pre></div></div>
<p>Then, start Yeoman:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">yo</span> code</span></code></pre></div></div>
<p>You will see a welcome to the VS Code extension generator.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/positron-theme/images/6-yeoman.png" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<p>Here’s what I inputted into the Yeoman prompt, advancing through each field by pressing <kbd>Enter</kbd>:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Yeoman Prompt</th>
<th>Response</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>What type of extension do you want to create?</strong></td>
<td><code>New Color Theme</code></td>
</tr>
<tr class="even">
<td><strong>Do you want to import or convert an existing TextMate color theme?</strong></td>
<td><code>Yes, import an existing theme and inline it in the Visual Studio Code color theme file.</code></td>
</tr>
<tr class="odd">
<td><strong>URL or filename to import:</strong></td>
<td><code>https://raw.githubusercontent.com/chriskempson/tomorrow-theme/refs/heads/master/textmate/Tomorrow-Night-Bright.tmTheme</code></td>
</tr>
<tr class="even">
<td><strong>What’s the name of your extension?</strong></td>
<td><code>tomorrow-night-bright-r-classic</code></td>
</tr>
<tr class="odd">
<td><strong>What’s the identifier of your extension?</strong></td>
<td><code>tomorrow-night-bright-r-classic</code></td>
</tr>
<tr class="even">
<td><strong>What’s the description of your extension?</strong></td>
<td><code>A Tomorrow Night Bright theme for Positron IDE and VS Code, inspired by RStudio IDE</code></td>
</tr>
<tr class="odd">
<td><strong>What’s the name of your theme shown to the user?</strong></td>
<td><code>Tomorrow Night Bright (R Classic)</code></td>
</tr>
<tr class="even">
<td><strong>Select a base theme:</strong></td>
<td><code>Dark</code></td>
</tr>
<tr class="odd">
<td><strong>Initialize a git repository?</strong></td>
<td><code>Yes</code></td>
</tr>
</tbody>
</table>
<p>Yeoman created the following files in the extension’s directory:<sup>2</sup></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">fs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dir_tree</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~/rrr/tomorrow-night-bright-r-classic"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">all =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb8-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ~/rrr/tomorrow-night-bright-r-classic</span></span>
<span id="cb8-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── .gitattributes</span></span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── .gitignore</span></span>
<span id="cb8-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── .vscode</span></span>
<span id="cb8-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; │   ├── launch.json</span></span>
<span id="cb8-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── .vscodeignore</span></span>
<span id="cb8-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── CHANGELOG.md</span></span>
<span id="cb8-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── README.md</span></span>
<span id="cb8-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── package.json</span></span>
<span id="cb8-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── themes</span></span>
<span id="cb8-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; │   └── tomorrow-night-bright-r-classic.json</span></span>
<span id="cb8-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; ├── vsc-extension-quickstart.md</span></span></code></pre></div></div>
<p>The resulting folder contains all of the files necessary for the color theme extension.</p>
<ul>
<li><code>package.json</code> - this is the manifest file that defines the location of the theme file and specifies the base theme.</li>
<li><code>themes/tomorrow-night-bright-r-classic.json</code> - the color theme definition file.</li>
<li><code>vsc-extension-quickstart.md</code> - this serves mainly as reference and you can feel free to delete it after reading it.</li>
</ul>
<p>If you open the folder in Positron and press <kbd>F5</kbd>, it will open a new Positron window with the header <code>[Extension Development Host]</code> which has your extension loaded. From there, open the Command Palette with <kbd>Shift</kbd>+<kbd>Cmd</kbd>+<kbd>P</kbd> and navigate to <code>Preferences: Color Theme</code> where you can select <code>Tomorrow Night Bright (R Classic)</code>.</p>
<p>Right now, it looks identical to the Microsoft port of Tomorrow Night Bright and is far from a perfect match for RStudio’s implementation. Let’s customize!</p>
</section>
</section>
<section id="customizing-the-extension" class="level2">
<h2 class="anchored" data-anchor-id="customizing-the-extension">Customizing the extension</h2>
<p>First, gather all of the color themes that you’ll use for inspiration. In our case, the file <code>tomorrow-night-bright-r-classic.json</code> in our local extension created by Yeoman currently mirrors the Microsoft port of Tomorrow Night Bright. The next steps for us were:</p>
<ul>
<li>Inspect the colors in GitHub Dark Default. If you have it installed, the theme file is located at <code>~/.positron/extensions/github.github-vscode-theme-6.3.5-universal/themes/dark-default.json</code> or similar depending on the version of your copy.</li>
<li>Change a color setting in <code>tomorrow-night-bright-r-classic.json</code> and review how it impacts your theme in the <code>[Extension Development Host]</code> window.</li>
<li>Wash, rinse, and repeat until you’re happy with how your new extension looks!</li>
</ul>
<p>This is the part of extension development that took the most time. It would be difficult to walk you through all of the individual design decisions we made while porting the theme. Briefly, since GitHub Dark Default is a great dark extension, it helped a lot to start with its settings, then to tweak its colors to superimpose editor and workbench colors specific to Tomorrow Night Bright. We kept most of GitHub Dark Default’s workbench colors, except that we changed its workbench green/orange accent colors to blue/orange accent colors — to match the Tomorrow Night Bright theme and aesthetic. In the end, we were able to port the editor colors to behave quite close to how they do in RStudio. We’re quite happy with the result!</p>
<p>Below I’ve reproduced tabsets with editor and workbench colors across the original Tomorrow Night Bright, original GitHub Dark Default, and the new Tomorrow Night Bright (R Classic) for reference. If you’re interested in seeing the R code we used to tame three JSON theme files into the tabsets below, you can find it <a href="https://github.com/ivelasq/pipedream/tree/main/blog/positron-theme/R/pluck_colors.R">here</a>.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Statistics (created with in-line R code)
</div>
</div>
<div class="callout-body-container callout-body">
<ul>
<li>Tomorrow Night Bright (Original) has 22 unique editor colors and 6 unique workbench colors.</li>
<li>GitHub Dark Default has 14 unique editor colors and 73 unique workbench colors.</li>
<li>Tomorrow Night Bright (R Classic) has 13 unique editor colors and 86 unique workbench colors.</li>
</ul>
</div>
</div>
</section>
<section id="editor-colors" class="level2">
<h2 class="anchored" data-anchor-id="editor-colors">Editor Colors</h2>
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs"><li class="nav-item"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" aria-controls="tabset-1-1" aria-selected="true" href="">Tomorrow Night Bright (Original)</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" aria-controls="tabset-1-2" aria-selected="false" href="">GitHub Dark Default</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-3-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-3" aria-controls="tabset-1-3" aria-selected="false" href="">Tomorrow Night Bright (R Classic)</a></li></ul>
<div class="tab-content">
<div id="tabset-1-1" class="tab-pane active" aria-labelledby="tabset-1-1-tab">
<div class="cell">
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;" data-quarto-table-cell-role="th">color</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">setting</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">scope</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left; width: 8em;">#000000<span style="display: inline-block; color: #000000; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #000000 (click to copy)" aria-label="Colour preview: #000000 (click to copy)" onclick="navigator.clipboard.writeText('#000000').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #000000'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">NA</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#191919<span style="display: inline-block; color: #191919; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #191919 (click to copy)" aria-label="Colour preview: #191919 (click to copy)" onclick="navigator.clipboard.writeText('#191919').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #191919'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">gutter</td>
<td style="text-align: left;">NA</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#404040<span style="display: inline-block; color: #404040; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #404040 (click to copy)" aria-label="Colour preview: #404040 (click to copy)" onclick="navigator.clipboard.writeText('#404040').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #404040'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">gutterForeground</td>
<td style="text-align: left;">NA</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#dedede<span style="display: inline-block; color: #dedede; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #dedede (click to copy)" aria-label="Colour preview: #dedede (click to copy)" onclick="navigator.clipboard.writeText('#dedede').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #dedede'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">NA</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#3e999f<span style="display: inline-block; color: #3e999f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3e999f (click to copy)" aria-label="Colour preview: #3e999f (click to copy)" onclick="navigator.clipboard.writeText('#3e999f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3e999f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">meta.diff.range</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#4271ae<span style="display: inline-block; color: #4271ae; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #4271ae (click to copy)" aria-label="Colour preview: #4271ae (click to copy)" onclick="navigator.clipboard.writeText('#4271ae').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #4271ae'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">meta.diff.header.from-file, meta.diff.header.to-file</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#70c0b1<span style="display: inline-block; color: #70c0b1; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #70c0b1 (click to copy)" aria-label="Colour preview: #70c0b1 (click to copy)" onclick="navigator.clipboard.writeText('#70c0b1').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #70c0b1'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.other.color, keyword.operator</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#718c00<span style="display: inline-block; color: #718c00; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #718c00 (click to copy)" aria-label="Colour preview: #718c00 (click to copy)" onclick="navigator.clipboard.writeText('#718c00').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #718c00'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">markup.inserted.diff, meta.diff.header.to-file</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#7aa6da<span style="display: inline-block; color: #7aa6da; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #7aa6da (click to copy)" aria-label="Colour preview: #7aa6da (click to copy)" onclick="navigator.clipboard.writeText('#7aa6da').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #7aa6da'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name.function, keyword.other.special-method, markup.changed.git_gutter, meta.block-level, meta.function-call, support.function</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#82a3bf<span style="display: inline-block; color: #82a3bf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #82a3bf (click to copy)" aria-label="Colour preview: #82a3bf (click to copy)" onclick="navigator.clipboard.writeText('#82a3bf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #82a3bf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">meta.separator</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#969896<span style="display: inline-block; color: #969896; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #969896 (click to copy)" aria-label="Colour preview: #969896 (click to copy)" onclick="navigator.clipboard.writeText('#969896').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #969896'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">comment</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#b798bf<span style="display: inline-block; color: #b798bf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #b798bf (click to copy)" aria-label="Colour preview: #b798bf (click to copy)" onclick="navigator.clipboard.writeText('#b798bf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #b798bf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">invalid.deprecated</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#b9ca4a<span style="display: inline-block; color: #b9ca4a; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #b9ca4a (click to copy)" aria-label="Colour preview: #b9ca4a (click to copy)" onclick="navigator.clipboard.writeText('#b9ca4a').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #b9ca4a'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.other.symbol, entity.name.filename, entity.other.inherited-class, markup.heading, markup.inserted.git_gutter, string</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#c397d8<span style="display: inline-block; color: #c397d8; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #c397d8 (click to copy)" aria-label="Colour preview: #c397d8 (click to copy)" onclick="navigator.clipboard.writeText('#c397d8').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #c397d8'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name.tag.css, keyword, storage, storage.type</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#ced2cf<span style="display: inline-block; color: #ced2cf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ced2cf (click to copy)" aria-label="Colour preview: #ced2cf (click to copy)" onclick="navigator.clipboard.writeText('#ced2cf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ced2cf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">invalid, invalid.deprecated, meta.separator</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#d54e53<span style="display: inline-block; color: #d54e53; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #d54e53 (click to copy)" aria-label="Colour preview: #d54e53 (click to copy)" onclick="navigator.clipboard.writeText('#d54e53').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #d54e53'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">declaration.tag, entity.name.tag, entity.other.attribute-name, markup.deleted.git_gutter, meta.tag, string.other.link, string.regexp, support.other.variable, variable</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#df5f5f<span style="display: inline-block; color: #df5f5f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #df5f5f (click to copy)" aria-label="Colour preview: #df5f5f (click to copy)" onclick="navigator.clipboard.writeText('#df5f5f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #df5f5f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">invalid</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#e78c45<span style="display: inline-block; color: #e78c45; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e78c45 (click to copy)" aria-label="Colour preview: #e78c45 (click to copy)" onclick="navigator.clipboard.writeText('#e78c45').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e78c45'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.character, constant.language, constant.numeric, keyword.other.unit, punctuation.section.embedded, support.constant, variable.parameter</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#e7c547<span style="display: inline-block; color: #e7c547; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e7c547 (click to copy)" aria-label="Colour preview: #e7c547 (click to copy)" onclick="navigator.clipboard.writeText('#e7c547').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e7c547'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name.class, entity.name.type.class, support.class, support.type</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#eeeeee<span style="display: inline-block; color: #eeeeee; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #eeeeee (click to copy)" aria-label="Colour preview: #eeeeee (click to copy)" onclick="navigator.clipboard.writeText('#eeeeee').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #eeeeee'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.other, keyword.operator.class, source.php.embedded.line</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#ffffff<span style="display: inline-block; color: #ffffff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ffffff (click to copy)" aria-label="Colour preview: #ffffff (click to copy)" onclick="navigator.clipboard.writeText('#ffffff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ffffff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">markup.deleted.diff, markup.inserted.diff, meta.diff.header.from-file, meta.diff.header.from-file, meta.diff.header.to-file, meta.diff.header.to-file</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#c82829<span style="display: inline-block; color: #c82829; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #c82829 (click to copy)" aria-label="Colour preview: #c82829 (click to copy)" onclick="navigator.clipboard.writeText('#c82829').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #c82829'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">markup.deleted.diff, meta.diff.header.from-file</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="tabset-1-2" class="tab-pane" aria-labelledby="tabset-1-2-tab">
<div class="cell">
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;" data-quarto-table-cell-role="th">color</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">setting</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">scope</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left; width: 8em;">#04260f<span style="display: inline-block; color: #04260f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #04260f (click to copy)" aria-label="Colour preview: #04260f (click to copy)" onclick="navigator.clipboard.writeText('#04260f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #04260f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">markup.inserted, meta.diff.header.to-file, punctuation.definition.inserted</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#161b22<span style="display: inline-block; color: #161b22; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #161b22 (click to copy)" aria-label="Colour preview: #161b22 (click to copy)" onclick="navigator.clipboard.writeText('#161b22').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #161b22'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">markup.ignored, markup.untracked</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#490202<span style="display: inline-block; color: #490202; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #490202 (click to copy)" aria-label="Colour preview: #490202 (click to copy)" onclick="navigator.clipboard.writeText('#490202').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #490202'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">markup.deleted, meta.diff.header.from-file, punctuation.definition.deleted</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#5a1e02<span style="display: inline-block; color: #5a1e02; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #5a1e02 (click to copy)" aria-label="Colour preview: #5a1e02 (click to copy)" onclick="navigator.clipboard.writeText('#5a1e02').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #5a1e02'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">markup.changed, punctuation.definition.changed</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#79c0ff<span style="display: inline-block; color: #79c0ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #79c0ff (click to copy)" aria-label="Colour preview: #79c0ff (click to copy)" onclick="navigator.clipboard.writeText('#79c0ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #79c0ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">markup.ignored, markup.untracked</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#79c0ff<span style="display: inline-block; color: #79c0ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #79c0ff (click to copy)" aria-label="Colour preview: #79c0ff (click to copy)" onclick="navigator.clipboard.writeText('#79c0ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #79c0ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant, entity, entity.name.constant, markup.heading, markup.heading entity.name, markup.inline.raw, meta.diff.header, meta.module-reference, meta.output, meta.property-name, meta.separator, string variable, support, support.constant, support.variable, variable.language, variable.other.constant, variable.other.enummember</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#7ee787<span style="display: inline-block; color: #7ee787; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #7ee787 (click to copy)" aria-label="Colour preview: #7ee787 (click to copy)" onclick="navigator.clipboard.writeText('#7ee787').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #7ee787'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name.tag, markup.inserted, markup.quote, meta.diff.header.to-file, punctuation.definition.inserted, string.regexp constant.character.escape, support.class.component, support.type.property-name.json</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">brackethighlighter.angle, brackethighlighter.curly, brackethighlighter.quote, brackethighlighter.round, brackethighlighter.square, brackethighlighter.tag, comment, punctuation.definition.comment, string.comment</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#a5d6ff<span style="display: inline-block; color: #a5d6ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #a5d6ff (click to copy)" aria-label="Colour preview: #a5d6ff (click to copy)" onclick="navigator.clipboard.writeText('#a5d6ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #a5d6ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.other.reference.link, source.regexp, string, string punctuation.section.embedded source, string.other.link, string.regexp, string.regexp constant.character.escape, string.regexp source.ruby.embedded, string.regexp string.regexp.arbitrary-repitition, string.regexp.character-class</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#d2a8ff<span style="display: inline-block; color: #d2a8ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #d2a8ff (click to copy)" aria-label="Colour preview: #d2a8ff (click to copy)" onclick="navigator.clipboard.writeText('#d2a8ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #d2a8ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name.function, meta.diff.range</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name.constant, markup.bold, markup.italic, meta.block, meta.embedded.expression, meta.jsx.children, meta.object.member, meta.tag.attributes, storage.modifier.import, storage.modifier.package, storage.type.java, variable.other, variable.parameter.function</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#f0f6fc<span style="display: inline-block; color: #f0f6fc; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f0f6fc (click to copy)" aria-label="Colour preview: #f0f6fc (click to copy)" onclick="navigator.clipboard.writeText('#f0f6fc').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f0f6fc'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">carriage-return</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#ff7b72<span style="display: inline-block; color: #ff7b72; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ff7b72 (click to copy)" aria-label="Colour preview: #ff7b72 (click to copy)" onclick="navigator.clipboard.writeText('#ff7b72').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ff7b72'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">carriage-return</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#ff7b72<span style="display: inline-block; color: #ff7b72; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ff7b72 (click to copy)" aria-label="Colour preview: #ff7b72 (click to copy)" onclick="navigator.clipboard.writeText('#ff7b72').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ff7b72'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.character, constant.other.placeholder, keyword, punctuation.section.embedded, storage, storage.type</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#ffa198<span style="display: inline-block; color: #ffa198; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ffa198 (click to copy)" aria-label="Colour preview: #ffa198 (click to copy)" onclick="navigator.clipboard.writeText('#ffa198').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ffa198'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">brackethighlighter.unmatched, invalid.broken, invalid.deprecated, invalid.illegal, invalid.unimplemented, markup.deleted, message.error, meta.diff.header.from-file, punctuation.definition.deleted</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#ffa657<span style="display: inline-block; color: #ffa657; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ffa657 (click to copy)" aria-label="Colour preview: #ffa657 (click to copy)" onclick="navigator.clipboard.writeText('#ffa657').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ffa657'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name, markup.changed, meta.definition.variable, meta.export.default, punctuation.definition.changed, punctuation.definition.list.begin.markdown, variable</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="tabset-1-3" class="tab-pane" aria-labelledby="tabset-1-3-tab">
<div class="cell">
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;" data-quarto-table-cell-role="th">color</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">setting</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">scope</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left; width: 8em;">#000000<span style="display: inline-block; color: #000000; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #000000 (click to copy)" aria-label="Colour preview: #000000 (click to copy)" onclick="navigator.clipboard.writeText('#000000').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #000000'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">NA</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#dedede<span style="display: inline-block; color: #dedede; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #dedede (click to copy)" aria-label="Colour preview: #dedede (click to copy)" onclick="navigator.clipboard.writeText('#dedede').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #dedede'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">NA</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#70c0b1<span style="display: inline-block; color: #70c0b1; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #70c0b1 (click to copy)" aria-label="Colour preview: #70c0b1 (click to copy)" onclick="navigator.clipboard.writeText('#70c0b1').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #70c0b1'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.other.color, keyword.operator</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#82a3bf<span style="display: inline-block; color: #82a3bf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #82a3bf (click to copy)" aria-label="Colour preview: #82a3bf (click to copy)" onclick="navigator.clipboard.writeText('#82a3bf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #82a3bf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">meta.separator</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#969896<span style="display: inline-block; color: #969896; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #969896 (click to copy)" aria-label="Colour preview: #969896 (click to copy)" onclick="navigator.clipboard.writeText('#969896').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #969896'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">comment</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#b798bf<span style="display: inline-block; color: #b798bf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #b798bf (click to copy)" aria-label="Colour preview: #b798bf (click to copy)" onclick="navigator.clipboard.writeText('#b798bf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #b798bf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">invalid.deprecated</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#b9ca4a<span style="display: inline-block; color: #b9ca4a; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #b9ca4a (click to copy)" aria-label="Colour preview: #b9ca4a (click to copy)" onclick="navigator.clipboard.writeText('#b9ca4a').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #b9ca4a'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.other.symbol, entity.other.inherited-class, markup.heading, string</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#c397d8<span style="display: inline-block; color: #c397d8; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #c397d8 (click to copy)" aria-label="Colour preview: #c397d8 (click to copy)" onclick="navigator.clipboard.writeText('#c397d8').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #c397d8'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name.tag.css, keyword, storage, storage.type</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#ced2cf<span style="display: inline-block; color: #ced2cf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ced2cf (click to copy)" aria-label="Colour preview: #ced2cf (click to copy)" onclick="navigator.clipboard.writeText('#ced2cf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ced2cf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">invalid, invalid.deprecated, meta.separator</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#dedede<span style="display: inline-block; color: #dedede; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #dedede (click to copy)" aria-label="Colour preview: #dedede (click to copy)" onclick="navigator.clipboard.writeText('#dedede').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #dedede'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.character, declaration.tag, entity.name.function, entity.name.tag, entity.other.attribute-name, keyword.other.special-method, keyword.other.unit, meta.block-level, meta.function-call, meta.tag, punctuation.section.embedded, string.other.link, string.regexp, support.constant, support.function, support.other.variable, variable, variable.parameter</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#df5f5f<span style="display: inline-block; color: #df5f5f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #df5f5f (click to copy)" aria-label="Colour preview: #df5f5f (click to copy)" onclick="navigator.clipboard.writeText('#df5f5f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #df5f5f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">background</td>
<td style="text-align: left;">invalid</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#e78c45<span style="display: inline-block; color: #e78c45; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e78c45 (click to copy)" aria-label="Colour preview: #e78c45 (click to copy)" onclick="navigator.clipboard.writeText('#e78c45').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e78c45'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.language, constant.numeric</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#e7c547<span style="display: inline-block; color: #e7c547; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e7c547 (click to copy)" aria-label="Colour preview: #e7c547 (click to copy)" onclick="navigator.clipboard.writeText('#e7c547').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e7c547'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">entity.name.class, entity.name.type.class, support.class, support.type</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#eeeeee<span style="display: inline-block; color: #eeeeee; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #eeeeee (click to copy)" aria-label="Colour preview: #eeeeee (click to copy)" onclick="navigator.clipboard.writeText('#eeeeee').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #eeeeee'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">foreground</td>
<td style="text-align: left;">constant.other, keyword.operator.class, source.php.embedded.line</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="workbench-colors" class="level2">
<h2 class="anchored" data-anchor-id="workbench-colors">Workbench Colors</h2>
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs"><li class="nav-item"><a class="nav-link active" id="tabset-2-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-1" aria-controls="tabset-2-1" aria-selected="true" href="">Tomorrow Night Bright (Original)</a></li><li class="nav-item"><a class="nav-link" id="tabset-2-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-2" aria-controls="tabset-2-2" aria-selected="false" href="">GitHub Dark Default</a></li><li class="nav-item"><a class="nav-link" id="tabset-2-3-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-3" aria-controls="tabset-2-3" aria-selected="false" href="">Tomorrow Night Bright (R Classic)</a></li></ul>
<div class="tab-content">
<div id="tabset-2-1" class="tab-pane active" aria-labelledby="tabset-2-1-tab">
<div class="cell">
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;" data-quarto-table-cell-role="th">color</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">setting</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left; width: 8em;">#000000<span style="display: inline-block; color: #000000; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #000000 (click to copy)" aria-label="Colour preview: #000000 (click to copy)" onclick="navigator.clipboard.writeText('#000000').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #000000'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.background</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#2a2a2a<span style="display: inline-block; color: #2a2a2a; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2a2a2a (click to copy)" aria-label="Colour preview: #2a2a2a (click to copy)" onclick="navigator.clipboard.writeText('#2a2a2a').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2a2a2a'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.lineHighlightBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#343434<span style="display: inline-block; color: #343434; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #343434 (click to copy)" aria-label="Colour preview: #343434 (click to copy)" onclick="navigator.clipboard.writeText('#343434').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #343434'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorWhitespace.foreground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#424242<span style="display: inline-block; color: #424242; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #424242 (click to copy)" aria-label="Colour preview: #424242 (click to copy)" onclick="navigator.clipboard.writeText('#424242').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #424242'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.selectionBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#9f9f9f<span style="display: inline-block; color: #9f9f9f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #9f9f9f (click to copy)" aria-label="Colour preview: #9f9f9f (click to copy)" onclick="navigator.clipboard.writeText('#9f9f9f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #9f9f9f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorCursor.foreground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#dedede<span style="display: inline-block; color: #dedede; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #dedede (click to copy)" aria-label="Colour preview: #dedede (click to copy)" onclick="navigator.clipboard.writeText('#dedede').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #dedede'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.foreground</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="tabset-2-2" class="tab-pane" aria-labelledby="tabset-2-2-tab">
<div class="cell">
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;" data-quarto-table-cell-role="th">color</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">setting</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left; width: 8em;">#010409<span style="display: inline-block; color: #010409; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #010409 (click to copy)" aria-label="Colour preview: #010409 (click to copy)" onclick="navigator.clipboard.writeText('#010409').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #010409'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorGroupHeader.tabsBackground, editorOverviewRuler.border, panel.background, sideBar.background, sideBarSectionHeader.background, tab.inactiveBackground, textBlockQuote.background, titleBar.inactiveBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#033a16<span style="display: inline-block; color: #033a16; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #033a16 (click to copy)" aria-label="Colour preview: #033a16 (click to copy)" onclick="navigator.clipboard.writeText('#033a16').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #033a16'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #04260f<span style="display: inline-block; color: #04260f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #04260f (click to copy)" aria-label="Colour preview: #04260f (click to copy)" onclick="navigator.clipboard.writeText('#04260f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #04260f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #0f5323<span style="display: inline-block; color: #0f5323; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #0f5323 (click to copy)" aria-label="Colour preview: #0f5323 (click to copy)" onclick="navigator.clipboard.writeText('#0f5323').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #0f5323'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #196c2e<span style="display: inline-block; color: #196c2e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #196c2e (click to copy)" aria-label="Colour preview: #196c2e (click to copy)" onclick="navigator.clipboard.writeText('#196c2e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #196c2e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #238636<span style="display: inline-block; color: #238636; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #238636 (click to copy)" aria-label="Colour preview: #238636 (click to copy)" onclick="navigator.clipboard.writeText('#238636').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #238636'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #2ea043<span style="display: inline-block; color: #2ea043; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2ea043 (click to copy)" aria-label="Colour preview: #2ea043 (click to copy)" onclick="navigator.clipboard.writeText('#2ea043').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2ea043'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #3fb950<span style="display: inline-block; color: #3fb950; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3fb950 (click to copy)" aria-label="Colour preview: #3fb950 (click to copy)" onclick="navigator.clipboard.writeText('#3fb950').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3fb950'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #56d364<span style="display: inline-block; color: #56d364; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #56d364 (click to copy)" aria-label="Colour preview: #56d364 (click to copy)" onclick="navigator.clipboard.writeText('#56d364').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #56d364'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #7ee787<span style="display: inline-block; color: #7ee787; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #7ee787 (click to copy)" aria-label="Colour preview: #7ee787 (click to copy)" onclick="navigator.clipboard.writeText('#7ee787').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #7ee787'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #aff5b4<span style="display: inline-block; color: #aff5b4; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #aff5b4 (click to copy)" aria-label="Colour preview: #aff5b4 (click to copy)" onclick="navigator.clipboard.writeText('#aff5b4').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #aff5b4'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.constantForeground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#0d1117<span style="display: inline-block; color: #0d1117; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #0d1117 (click to copy)" aria-label="Colour preview: #0d1117 (click to copy)" onclick="navigator.clipboard.writeText('#0d1117').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #0d1117'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.background, editor.background, input.background, peekViewResult.background, statusBar.background, statusBar.noFolderBackground, tab.activeBackground, tab.activeBorder, tab.hoverBackground, tab.unfocusedActiveBorder, titleBar.activeBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#161b22<span style="display: inline-block; color: #161b22; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #161b22 (click to copy)" aria-label="Colour preview: #161b22 (click to copy)" onclick="navigator.clipboard.writeText('#161b22').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #161b22'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">breadcrumbPicker.background, checkbox.background, debugToolBar.background, dropdown.background, dropdown.listBackground, editorWidget.background, notificationCenterHeader.background, notifications.background, quickInput.background</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#1f6feb<span style="display: inline-block; color: #1f6feb; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #1f6feb (click to copy)" aria-label="Colour preview: #1f6feb (click to copy)" onclick="navigator.clipboard.writeText('#1f6feb').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #1f6feb'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBarBadge.background, badge.background, focusBorder, progressBar.background, statusBarItem.focusBorder</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#1f6feb<span style="display: inline-block; color: #1f6feb; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #1f6feb (click to copy)" aria-label="Colour preview: #1f6feb (click to copy)" onclick="navigator.clipboard.writeText('#1f6feb').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #1f6feb'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>80</td>
<td style="text-align: left;">statusBar.focusBorder</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#21262d<span style="display: inline-block; color: #21262d; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #21262d (click to copy)" aria-label="Colour preview: #21262d (click to copy)" onclick="navigator.clipboard.writeText('#21262d').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #21262d'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">textSeparator.foreground, tree.indentGuidesStroke, welcomePage.buttonBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#238636<span style="display: inline-block; color: #238636; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #238636 (click to copy)" aria-label="Colour preview: #238636 (click to copy)" onclick="navigator.clipboard.writeText('#238636').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #238636'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">button.background</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#238636<span style="display: inline-block; color: #238636; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #238636 (click to copy)" aria-label="Colour preview: #238636 (click to copy)" onclick="navigator.clipboard.writeText('#238636').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #238636'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>26</td>
<td style="text-align: left;">diffEditor.insertedLineBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#282e33<span style="display: inline-block; color: #282e33; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #282e33 (click to copy)" aria-label="Colour preview: #282e33 (click to copy)" onclick="navigator.clipboard.writeText('#282e33').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #282e33'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">button.secondaryBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#2ea043<span style="display: inline-block; color: #2ea043; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2ea043 (click to copy)" aria-label="Colour preview: #2ea043 (click to copy)" onclick="navigator.clipboard.writeText('#2ea043').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2ea043'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">button.hoverBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#2ea043<span style="display: inline-block; color: #2ea043; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2ea043 (click to copy)" aria-label="Colour preview: #2ea043 (click to copy)" onclick="navigator.clipboard.writeText('#2ea043').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2ea043'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>66</td>
<td style="text-align: left;">editor.focusedStackFrameHighlightBackground, editorGutter.addedBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#2f81f7<span style="display: inline-block; color: #2f81f7; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2f81f7 (click to copy)" aria-label="Colour preview: #2f81f7 (click to copy)" onclick="navigator.clipboard.writeText('#2f81f7').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2f81f7'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorCursor.foreground, list.highlightForeground, notificationsInfoIcon.foreground, textLink.activeForeground, textLink.foreground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#2f81f7<span style="display: inline-block; color: #2f81f7; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2f81f7 (click to copy)" aria-label="Colour preview: #2f81f7 (click to copy)" onclick="navigator.clipboard.writeText('#2f81f7').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2f81f7'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>12</td>
<td style="text-align: left;">editor.linkedEditingBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#30363d<span style="display: inline-block; color: #30363d; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #30363d (click to copy)" aria-label="Colour preview: #30363d (click to copy)" onclick="navigator.clipboard.writeText('#30363d').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #30363d'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.border, button.secondaryHoverBackground, checkbox.border, dropdown.border, editorGroup.border, editorGroupHeader.tabsBorder, input.border, notifications.border, panel.border, panelInput.border, pickerGroup.border, sideBar.border, sideBarSectionHeader.border, statusBar.border, statusBarItem.remoteBackground, tab.border, tab.unfocusedActiveBorderTop, textBlockQuote.border, titleBar.border, welcomePage.buttonHoverBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#388bfd<span style="display: inline-block; color: #388bfd; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #388bfd (click to copy)" aria-label="Colour preview: #388bfd (click to copy)" onclick="navigator.clipboard.writeText('#388bfd').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #388bfd'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>26</td>
<td style="text-align: left;">list.focusBackground, list.inactiveFocusBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#39c5cf<span style="display: inline-block; color: #39c5cf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #39c5cf (click to copy)" aria-label="Colour preview: #39c5cf (click to copy)" onclick="navigator.clipboard.writeText('#39c5cf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #39c5cf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">terminal.ansiCyan</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#3fb950<span style="display: inline-block; color: #3fb950; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3fb950 (click to copy)" aria-label="Colour preview: #3fb950 (click to copy)" onclick="navigator.clipboard.writeText('#3fb950').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3fb950'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">gitDecoration.addedResourceForeground, gitDecoration.untrackedResourceForeground, symbolIcon.numberForeground, terminal.ansiGreen</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#3fb950<span style="display: inline-block; color: #3fb950; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3fb950 (click to copy)" aria-label="Colour preview: #3fb950 (click to copy)" onclick="navigator.clipboard.writeText('#3fb950').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3fb950'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>40</td>
<td style="text-align: left;">editor.selectionHighlightBackground, editorBracketMatch.background</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#3fb950<span style="display: inline-block; color: #3fb950; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3fb950 (click to copy)" aria-label="Colour preview: #3fb950 (click to copy)" onclick="navigator.clipboard.writeText('#3fb950').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3fb950'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>4d</td>
<td style="text-align: left;">diffEditor.insertedTextBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#3fb950<span style="display: inline-block; color: #3fb950; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3fb950 (click to copy)" aria-label="Colour preview: #3fb950 (click to copy)" onclick="navigator.clipboard.writeText('#3fb950').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3fb950'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>99</td>
<td style="text-align: left;">editorBracketMatch.border</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#484f58<span style="display: inline-block; color: #484f58; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #484f58 (click to copy)" aria-label="Colour preview: #484f58 (click to copy)" onclick="navigator.clipboard.writeText('#484f58').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #484f58'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorWhitespace.foreground, terminal.ansiBlack</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#484f58<span style="display: inline-block; color: #484f58; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #484f58 (click to copy)" aria-label="Colour preview: #484f58 (click to copy)" onclick="navigator.clipboard.writeText('#484f58').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #484f58'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>33</td>
<td style="text-align: left;">scrollbar.shadow</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#56d364<span style="display: inline-block; color: #56d364; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #56d364 (click to copy)" aria-label="Colour preview: #56d364 (click to copy)" onclick="navigator.clipboard.writeText('#56d364').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #56d364'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugTokenExpression.boolean, debugTokenExpression.number, editorBracketHighlight.foreground2, terminal.ansiBrightGreen</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#56d4dd<span style="display: inline-block; color: #56d4dd; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #56d4dd (click to copy)" aria-label="Colour preview: #56d4dd (click to copy)" onclick="navigator.clipboard.writeText('#56d4dd').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #56d4dd'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">terminal.ansiBrightCyan</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#58a6ff<span style="display: inline-block; color: #58a6ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #58a6ff (click to copy)" aria-label="Colour preview: #58a6ff (click to copy)" onclick="navigator.clipboard.writeText('#58a6ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #58a6ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.booleanForeground, symbolIcon.enumeratorMemberForeground, symbolIcon.keyForeground, symbolIcon.nullForeground, symbolIcon.referenceForeground, symbolIcon.snippetForeground, symbolIcon.unitForeground, terminal.ansiBlue</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorLineNumber.foreground, gitDecoration.ignoredResourceForeground, input.placeholderForeground, symbolIcon.eventForeground, terminal.ansiBrightBlack</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>1a</td>
<td style="text-align: left;">editor.foldBackground, editor.lineHighlightBackground, list.hoverBackground, peekViewEditor.background, tab.unfocusedHoverBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>4d</td>
<td style="text-align: left;">editor.wordHighlightStrongBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>66</td>
<td style="text-align: left;">list.activeSelectionBackground, list.inactiveSelectionBackground, statusBarItem.prominentBackground, textCodeBlock.background, textPreformat.background</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>80</td>
<td style="text-align: left;">editor.wordHighlightBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>99</td>
<td style="text-align: left;">editor.wordHighlightBorder, editor.wordHighlightStrongBorder</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#79c0ff<span style="display: inline-block; color: #79c0ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #79c0ff (click to copy)" aria-label="Colour preview: #79c0ff (click to copy)" onclick="navigator.clipboard.writeText('#79c0ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #79c0ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugTokenExpression.name, editorBracketHighlight.foreground1, symbolIcon.colorForeground, symbolIcon.operatorForeground, symbolIcon.stringForeground, symbolIcon.textForeground, symbolIcon.typeParameterForeground, terminal.ansiBrightBlue</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#7d8590<span style="display: inline-block; color: #7d8590; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #7d8590 (click to copy)" aria-label="Colour preview: #7d8590 (click to copy)" onclick="navigator.clipboard.writeText('#7d8590').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #7d8590'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.inactiveForeground, breadcrumb.activeSelectionForeground, breadcrumb.foreground, descriptionForeground, editorBracketHighlight.unexpectedBracket.foreground, editorInlayHint.foreground, editorInlayHint.paramForeground, editorInlayHint.typeForeground, gitDecoration.submoduleResourceForeground, icon.foreground, notificationCenterHeader.foreground, panelTitle.inactiveForeground, pickerGroup.foreground, statusBar.foreground, tab.inactiveForeground, textPreformat.foreground, titleBar.activeForeground, titleBar.inactiveForeground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsole.infoForeground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>33</td>
<td style="text-align: left;">editorInlayHint.background, editorInlayHint.paramBackground, editorInlayHint.typeBackground, minimapSlider.background, scrollbarSlider.background</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>3d</td>
<td style="text-align: left;">minimapSlider.hoverBackground, scrollbarSlider.hoverBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>47</td>
<td style="text-align: left;">minimapSlider.activeBackground, scrollbarSlider.activeBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#9e6a03<span style="display: inline-block; color: #9e6a03; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #9e6a03 (click to copy)" aria-label="Colour preview: #9e6a03 (click to copy)" onclick="navigator.clipboard.writeText('#9e6a03').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #9e6a03'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.findMatchBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#a5d6ff<span style="display: inline-block; color: #a5d6ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #a5d6ff (click to copy)" aria-label="Colour preview: #a5d6ff (click to copy)" onclick="navigator.clipboard.writeText('#a5d6ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #a5d6ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugTokenExpression.string, debugTokenExpression.value</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#b1bac4<span style="display: inline-block; color: #b1bac4; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #b1bac4 (click to copy)" aria-label="Colour preview: #b1bac4 (click to copy)" onclick="navigator.clipboard.writeText('#b1bac4').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #b1bac4'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">terminal.ansiWhite</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#bb8009<span style="display: inline-block; color: #bb8009; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #bb8009 (click to copy)" aria-label="Colour preview: #bb8009 (click to copy)" onclick="navigator.clipboard.writeText('#bb8009').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #bb8009'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>66</td>
<td style="text-align: left;">editor.stackFrameHighlightBackground, editorGutter.modifiedBackground, peekViewEditor.matchHighlightBackground, peekViewResult.matchHighlightBackground, settings.modifiedItemIndicator</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#bc8cff<span style="display: inline-block; color: #bc8cff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #bc8cff (click to copy)" aria-label="Colour preview: #bc8cff (click to copy)" onclick="navigator.clipboard.writeText('#bc8cff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #bc8cff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsoleInputIcon.foreground, symbolIcon.functionForeground, symbolIcon.methodForeground, terminal.ansiMagenta</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#c9d1d9<span style="display: inline-block; color: #c9d1d9; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #c9d1d9 (click to copy)" aria-label="Colour preview: #c9d1d9 (click to copy)" onclick="navigator.clipboard.writeText('#c9d1d9').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #c9d1d9'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">button.secondaryForeground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#d29922<span style="display: inline-block; color: #d29922; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #d29922 (click to copy)" aria-label="Colour preview: #d29922 (click to copy)" onclick="navigator.clipboard.writeText('#d29922').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #d29922'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsole.warningForeground, gitDecoration.modifiedResourceForeground, notificationsWarningIcon.foreground, symbolIcon.fileForeground, symbolIcon.folderForeground, terminal.ansiYellow</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#d2a8ff<span style="display: inline-block; color: #d2a8ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #d2a8ff (click to copy)" aria-label="Colour preview: #d2a8ff (click to copy)" onclick="navigator.clipboard.writeText('#d2a8ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #d2a8ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground6, symbolIcon.constructorForeground, terminal.ansiBrightMagenta</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#da3633<span style="display: inline-block; color: #da3633; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #da3633 (click to copy)" aria-label="Colour preview: #da3633 (click to copy)" onclick="navigator.clipboard.writeText('#da3633').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #da3633'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">statusBar.debuggingBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#da3633<span style="display: inline-block; color: #da3633; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #da3633 (click to copy)" aria-label="Colour preview: #da3633 (click to copy)" onclick="navigator.clipboard.writeText('#da3633').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #da3633'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>26</td>
<td style="text-align: left;">diffEditor.removedLineBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#db6d28<span style="display: inline-block; color: #db6d28; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #db6d28 (click to copy)" aria-label="Colour preview: #db6d28 (click to copy)" onclick="navigator.clipboard.writeText('#db6d28').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #db6d28'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">gitDecoration.conflictingResourceForeground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#e3b341<span style="display: inline-block; color: #e3b341; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e3b341 (click to copy)" aria-label="Colour preview: #e3b341 (click to copy)" onclick="navigator.clipboard.writeText('#e3b341').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e3b341'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsole.sourceForeground, editorBracketHighlight.foreground3, terminal.ansiBrightYellow</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.foreground, breadcrumb.focusForeground, dropdown.foreground, editor.foreground, editorLineNumber.activeForeground, foreground, input.foreground, keybindingLabel.foreground, list.activeSelectionForeground, list.focusForeground, list.hoverForeground, list.inactiveSelectionForeground, notifications.foreground, panelTitle.activeForeground, quickInput.foreground, settings.headerForeground, sideBar.foreground, sideBarSectionHeader.foreground, sideBarTitle.foreground, statusBarItem.remoteForeground, tab.activeForeground, terminal.foreground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>14</td>
<td style="text-align: left;">statusBarItem.hoverBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>1f</td>
<td style="text-align: left;">editorIndentGuide.background, statusBarItem.activeBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>3d</td>
<td style="text-align: left;">editorIndentGuide.activeBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#f0883e<span style="display: inline-block; color: #f0883e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f0883e (click to copy)" aria-label="Colour preview: #f0883e (click to copy)" onclick="navigator.clipboard.writeText('#f0883e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f0883e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.arrayForeground, symbolIcon.classForeground, symbolIcon.enumeratorForeground, symbolIcon.fieldForeground, symbolIcon.interfaceForeground, symbolIcon.objectForeground, symbolIcon.packageForeground, symbolIcon.propertyForeground, symbolIcon.structForeground, symbolIcon.variableForeground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#f2cc60<span style="display: inline-block; color: #f2cc60; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f2cc60 (click to copy)" aria-label="Colour preview: #f2cc60 (click to copy)" onclick="navigator.clipboard.writeText('#f2cc60').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f2cc60'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>80</td>
<td style="text-align: left;">editor.findMatchHighlightBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#f78166<span style="display: inline-block; color: #f78166; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f78166 (click to copy)" aria-label="Colour preview: #f78166 (click to copy)" onclick="navigator.clipboard.writeText('#f78166').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f78166'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.activeBorder, panelTitle.activeBorder, tab.activeBorderTop</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#f85149<span style="display: inline-block; color: #f85149; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f85149 (click to copy)" aria-label="Colour preview: #f85149 (click to copy)" onclick="navigator.clipboard.writeText('#f85149').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f85149'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugIcon.breakpointForeground, errorForeground, gitDecoration.deletedResourceForeground, notificationsErrorIcon.foreground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#f85149<span style="display: inline-block; color: #f85149; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f85149 (click to copy)" aria-label="Colour preview: #f85149 (click to copy)" onclick="navigator.clipboard.writeText('#f85149').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f85149'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>66</td>
<td style="text-align: left;">editorGutter.deletedBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#ff7b72<span style="display: inline-block; color: #ff7b72; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ff7b72 (click to copy)" aria-label="Colour preview: #ff7b72 (click to copy)" onclick="navigator.clipboard.writeText('#ff7b72').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ff7b72'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.keywordForeground, symbolIcon.moduleForeground, symbolIcon.namespaceForeground, terminal.ansiRed</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#ff7b72<span style="display: inline-block; color: #ff7b72; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ff7b72 (click to copy)" aria-label="Colour preview: #ff7b72 (click to copy)" onclick="navigator.clipboard.writeText('#ff7b72').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ff7b72'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>4d</td>
<td style="text-align: left;">diffEditor.removedTextBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#ff9bce<span style="display: inline-block; color: #ff9bce; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ff9bce (click to copy)" aria-label="Colour preview: #ff9bce (click to copy)" onclick="navigator.clipboard.writeText('#ff9bce').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ff9bce'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground5</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 8em;">#ffa198<span style="display: inline-block; color: #ffa198; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ffa198 (click to copy)" aria-label="Colour preview: #ffa198 (click to copy)" onclick="navigator.clipboard.writeText('#ffa198').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ffa198'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsole.errorForeground, debugTokenExpression.error, editorBracketHighlight.foreground4, terminal.ansiBrightRed</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 8em;">#ffffff<span style="display: inline-block; color: #ffffff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ffffff (click to copy)" aria-label="Colour preview: #ffffff (click to copy)" onclick="navigator.clipboard.writeText('#ffffff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ffffff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBarBadge.foreground, badge.foreground, button.foreground, statusBar.debuggingForeground, terminal.ansiBrightWhite</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="tabset-2-3" class="tab-pane" aria-labelledby="tabset-2-3-tab">
<div class="cell">
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;" data-quarto-table-cell-role="th">color</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">setting</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left; width: 12em;">#000000<span style="display: inline-block; color: #000000; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #000000 (click to copy)" aria-label="Colour preview: #000000 (click to copy)" onclick="navigator.clipboard.writeText('#000000').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #000000'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.background, editor.lineHighlightBorder</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#00bdce<span style="display: inline-block; color: #00bdce; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #00bdce (click to copy)" aria-label="Colour preview: #00bdce (click to copy)" onclick="navigator.clipboard.writeText('#00bdce').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #00bdce'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground5</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#010409<span style="display: inline-block; color: #010409; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #010409 (click to copy)" aria-label="Colour preview: #010409 (click to copy)" onclick="navigator.clipboard.writeText('#010409').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #010409'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorGroupHeader.tabsBackground, editorOverviewRuler.border, panel.background, sideBar.background, sideBarSectionHeader.background, tab.inactiveBackground, textBlockQuote.background, titleBar.inactiveBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#033a16<span style="display: inline-block; color: #033a16; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #033a16 (click to copy)" aria-label="Colour preview: #033a16 (click to copy)" onclick="navigator.clipboard.writeText('#033a16').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #033a16'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #04260f<span style="display: inline-block; color: #04260f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #04260f (click to copy)" aria-label="Colour preview: #04260f (click to copy)" onclick="navigator.clipboard.writeText('#04260f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #04260f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #0f5323<span style="display: inline-block; color: #0f5323; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #0f5323 (click to copy)" aria-label="Colour preview: #0f5323 (click to copy)" onclick="navigator.clipboard.writeText('#0f5323').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #0f5323'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #196c2e<span style="display: inline-block; color: #196c2e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #196c2e (click to copy)" aria-label="Colour preview: #196c2e (click to copy)" onclick="navigator.clipboard.writeText('#196c2e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #196c2e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #238636<span style="display: inline-block; color: #238636; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #238636 (click to copy)" aria-label="Colour preview: #238636 (click to copy)" onclick="navigator.clipboard.writeText('#238636').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #238636'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #2ea043<span style="display: inline-block; color: #2ea043; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2ea043 (click to copy)" aria-label="Colour preview: #2ea043 (click to copy)" onclick="navigator.clipboard.writeText('#2ea043').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2ea043'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #3fb950<span style="display: inline-block; color: #3fb950; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3fb950 (click to copy)" aria-label="Colour preview: #3fb950 (click to copy)" onclick="navigator.clipboard.writeText('#3fb950').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3fb950'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #56d364<span style="display: inline-block; color: #56d364; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #56d364 (click to copy)" aria-label="Colour preview: #56d364 (click to copy)" onclick="navigator.clipboard.writeText('#56d364').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #56d364'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #7ee787<span style="display: inline-block; color: #7ee787; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #7ee787 (click to copy)" aria-label="Colour preview: #7ee787 (click to copy)" onclick="navigator.clipboard.writeText('#7ee787').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #7ee787'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>, #aff5b4<span style="display: inline-block; color: #aff5b4; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #aff5b4 (click to copy)" aria-label="Colour preview: #aff5b4 (click to copy)" onclick="navigator.clipboard.writeText('#aff5b4').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #aff5b4'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.constantForeground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#0d1117<span style="display: inline-block; color: #0d1117; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #0d1117 (click to copy)" aria-label="Colour preview: #0d1117 (click to copy)" onclick="navigator.clipboard.writeText('#0d1117').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #0d1117'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.background, input.background, peekViewResult.background, statusBar.background, statusBar.noFolderBackground, tab.activeBackground, tab.activeBorder, tab.hoverBackground, tab.unfocusedActiveBorder, titleBar.activeBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#161b22<span style="display: inline-block; color: #161b22; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #161b22 (click to copy)" aria-label="Colour preview: #161b22 (click to copy)" onclick="navigator.clipboard.writeText('#161b22').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #161b22'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">breadcrumbPicker.background, checkbox.background, debugToolBar.background, dropdown.background, dropdown.listBackground, editorWidget.background, notificationCenterHeader.background, notifications.background, quickInput.background</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#1f6feb<span style="display: inline-block; color: #1f6feb; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #1f6feb (click to copy)" aria-label="Colour preview: #1f6feb (click to copy)" onclick="navigator.clipboard.writeText('#1f6feb').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #1f6feb'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>80</td>
<td style="text-align: left;">statusBar.focusBorder</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#21262d<span style="display: inline-block; color: #21262d; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #21262d (click to copy)" aria-label="Colour preview: #21262d (click to copy)" onclick="navigator.clipboard.writeText('#21262d').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #21262d'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">textSeparator.foreground, tree.indentGuidesStroke, welcomePage.buttonBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#238636<span style="display: inline-block; color: #238636; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #238636 (click to copy)" aria-label="Colour preview: #238636 (click to copy)" onclick="navigator.clipboard.writeText('#238636').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #238636'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>26</td>
<td style="text-align: left;">diffEditor.insertedLineBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#282e33<span style="display: inline-block; color: #282e33; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #282e33 (click to copy)" aria-label="Colour preview: #282e33 (click to copy)" onclick="navigator.clipboard.writeText('#282e33').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #282e33'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">button.secondaryBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#2ea043<span style="display: inline-block; color: #2ea043; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2ea043 (click to copy)" aria-label="Colour preview: #2ea043 (click to copy)" onclick="navigator.clipboard.writeText('#2ea043').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2ea043'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>66</td>
<td style="text-align: left;">editor.focusedStackFrameHighlightBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#2f81f7<span style="display: inline-block; color: #2f81f7; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2f81f7 (click to copy)" aria-label="Colour preview: #2f81f7 (click to copy)" onclick="navigator.clipboard.writeText('#2f81f7').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2f81f7'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">list.highlightForeground, notificationsInfoIcon.foreground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#2f81f7<span style="display: inline-block; color: #2f81f7; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #2f81f7 (click to copy)" aria-label="Colour preview: #2f81f7 (click to copy)" onclick="navigator.clipboard.writeText('#2f81f7').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #2f81f7'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>12</td>
<td style="text-align: left;">editor.linkedEditingBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#30363d<span style="display: inline-block; color: #30363d; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #30363d (click to copy)" aria-label="Colour preview: #30363d (click to copy)" onclick="navigator.clipboard.writeText('#30363d').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #30363d'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.border, button.secondaryHoverBackground, checkbox.border, dropdown.border, editorGroup.border, editorGroupHeader.tabsBorder, input.border, notifications.border, panel.border, panelInput.border, pickerGroup.border, sideBar.border, sideBarSectionHeader.border, statusBar.border, statusBarItem.remoteBackground, tab.border, tab.unfocusedActiveBorderTop, textBlockQuote.border, titleBar.border, welcomePage.buttonHoverBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#32609b<span style="display: inline-block; color: #32609b; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #32609b (click to copy)" aria-label="Colour preview: #32609b (click to copy)" onclick="navigator.clipboard.writeText('#32609b').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #32609b'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">button.hoverBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#33c192<span style="display: inline-block; color: #33c192; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #33c192 (click to copy)" aria-label="Colour preview: #33c192 (click to copy)" onclick="navigator.clipboard.writeText('#33c192').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #33c192'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground4</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#343434<span style="display: inline-block; color: #343434; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #343434 (click to copy)" aria-label="Colour preview: #343434 (click to copy)" onclick="navigator.clipboard.writeText('#343434').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #343434'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorWhitespace.foreground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#388bfd<span style="display: inline-block; color: #388bfd; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #388bfd (click to copy)" aria-label="Colour preview: #388bfd (click to copy)" onclick="navigator.clipboard.writeText('#388bfd').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #388bfd'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>26</td>
<td style="text-align: left;">list.focusBackground, list.inactiveFocusBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#39c5cf<span style="display: inline-block; color: #39c5cf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #39c5cf (click to copy)" aria-label="Colour preview: #39c5cf (click to copy)" onclick="navigator.clipboard.writeText('#39c5cf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #39c5cf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">terminal.ansiCyan</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#3fb950<span style="display: inline-block; color: #3fb950; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3fb950 (click to copy)" aria-label="Colour preview: #3fb950 (click to copy)" onclick="navigator.clipboard.writeText('#3fb950').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3fb950'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.numberForeground, terminal.ansiGreen</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#3fb950<span style="display: inline-block; color: #3fb950; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #3fb950 (click to copy)" aria-label="Colour preview: #3fb950 (click to copy)" onclick="navigator.clipboard.writeText('#3fb950').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #3fb950'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>4d</td>
<td style="text-align: left;">diffEditor.insertedTextBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#424242<span style="display: inline-block; color: #424242; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #424242 (click to copy)" aria-label="Colour preview: #424242 (click to copy)" onclick="navigator.clipboard.writeText('#424242').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #424242'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.selectionBackground, editorBracketMatch.background, editorBracketMatch.border</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#4271ae<span style="display: inline-block; color: #4271ae; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #4271ae (click to copy)" aria-label="Colour preview: #4271ae (click to copy)" onclick="navigator.clipboard.writeText('#4271ae').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #4271ae'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBarBadge.background, badge.background, button.background, focusBorder, progressBar.background, statusBarItem.focusBorder</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#484f58<span style="display: inline-block; color: #484f58; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #484f58 (click to copy)" aria-label="Colour preview: #484f58 (click to copy)" onclick="navigator.clipboard.writeText('#484f58').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #484f58'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">terminal.ansiBlack</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#484f58<span style="display: inline-block; color: #484f58; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #484f58 (click to copy)" aria-label="Colour preview: #484f58 (click to copy)" onclick="navigator.clipboard.writeText('#484f58').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #484f58'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>33</td>
<td style="text-align: left;">scrollbar.shadow</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#5089d3<span style="display: inline-block; color: #5089d3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #5089d3 (click to copy)" aria-label="Colour preview: #5089d3 (click to copy)" onclick="navigator.clipboard.writeText('#5089d3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #5089d3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">textLink.activeForeground, textLink.foreground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#56d364<span style="display: inline-block; color: #56d364; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #56d364 (click to copy)" aria-label="Colour preview: #56d364 (click to copy)" onclick="navigator.clipboard.writeText('#56d364').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #56d364'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugTokenExpression.boolean, debugTokenExpression.number, terminal.ansiBrightGreen</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#56d4dd<span style="display: inline-block; color: #56d4dd; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #56d4dd (click to copy)" aria-label="Colour preview: #56d4dd (click to copy)" onclick="navigator.clipboard.writeText('#56d4dd').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #56d4dd'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">terminal.ansiBrightCyan</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#58a6ff<span style="display: inline-block; color: #58a6ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #58a6ff (click to copy)" aria-label="Colour preview: #58a6ff (click to copy)" onclick="navigator.clipboard.writeText('#58a6ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #58a6ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.booleanForeground, symbolIcon.enumeratorMemberForeground, symbolIcon.keyForeground, symbolIcon.nullForeground, symbolIcon.referenceForeground, symbolIcon.snippetForeground, symbolIcon.unitForeground, terminal.ansiBlue</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorLineNumber.foreground, input.placeholderForeground, symbolIcon.eventForeground, terminal.ansiBrightBlack</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>1a</td>
<td style="text-align: left;">editor.foldBackground, list.hoverBackground, peekViewEditor.background, tab.unfocusedHoverBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>4d</td>
<td style="text-align: left;">editor.wordHighlightStrongBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>66</td>
<td style="text-align: left;">list.activeSelectionBackground, list.inactiveSelectionBackground, statusBarItem.prominentBackground, textCodeBlock.background, textPreformat.background</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>80</td>
<td style="text-align: left;">editor.wordHighlightBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#6e7681<span style="display: inline-block; color: #6e7681; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #6e7681 (click to copy)" aria-label="Colour preview: #6e7681 (click to copy)" onclick="navigator.clipboard.writeText('#6e7681').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #6e7681'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>99</td>
<td style="text-align: left;">editor.wordHighlightBorder, editor.wordHighlightStrongBorder</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#70c0b1<span style="display: inline-block; color: #70c0b1; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #70c0b1 (click to copy)" aria-label="Colour preview: #70c0b1 (click to copy)" onclick="navigator.clipboard.writeText('#70c0b1').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #70c0b1'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorGutter.modifiedBackground, editorMarkerNavigationWarning.background, editorWarning.foreground, gitDecoration.addedResourceForeground, gitDecoration.modifiedResourceForeground, gitDecoration.untrackedResourceForeground, list.warningForeground, problemsWarningIcon.foreground, scmGraph.historyItemGroupLocal</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#79c0ff<span style="display: inline-block; color: #79c0ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #79c0ff (click to copy)" aria-label="Colour preview: #79c0ff (click to copy)" onclick="navigator.clipboard.writeText('#79c0ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #79c0ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugTokenExpression.name, symbolIcon.colorForeground, symbolIcon.operatorForeground, symbolIcon.stringForeground, symbolIcon.textForeground, symbolIcon.typeParameterForeground, terminal.ansiBrightBlue</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#7d8590<span style="display: inline-block; color: #7d8590; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #7d8590 (click to copy)" aria-label="Colour preview: #7d8590 (click to copy)" onclick="navigator.clipboard.writeText('#7d8590').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #7d8590'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.inactiveForeground, breadcrumb.activeSelectionForeground, breadcrumb.foreground, descriptionForeground, editorBracketHighlight.unexpectedBracket.foreground, editorInlayHint.foreground, editorInlayHint.paramForeground, editorInlayHint.typeForeground, icon.foreground, notificationCenterHeader.foreground, panelTitle.inactiveForeground, pickerGroup.foreground, statusBar.foreground, tab.inactiveForeground, textPreformat.foreground, titleBar.activeForeground, titleBar.inactiveForeground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#82a3bf<span style="display: inline-block; color: #82a3bf; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #82a3bf (click to copy)" aria-label="Colour preview: #82a3bf (click to copy)" onclick="navigator.clipboard.writeText('#82a3bf').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #82a3bf'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">scmGraph.foreground1</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsole.infoForeground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>33</td>
<td style="text-align: left;">editorInlayHint.background, editorInlayHint.paramBackground, editorInlayHint.typeBackground, minimapSlider.background, scrollbarSlider.background</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>3d</td>
<td style="text-align: left;">minimapSlider.hoverBackground, scrollbarSlider.hoverBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#8b949e<span style="display: inline-block; color: #8b949e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #8b949e (click to copy)" aria-label="Colour preview: #8b949e (click to copy)" onclick="navigator.clipboard.writeText('#8b949e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #8b949e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>47</td>
<td style="text-align: left;">minimapSlider.activeBackground, scrollbarSlider.activeBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#94a9ec<span style="display: inline-block; color: #94a9ec; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #94a9ec (click to copy)" aria-label="Colour preview: #94a9ec (click to copy)" onclick="navigator.clipboard.writeText('#94a9ec').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #94a9ec'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground6</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#99b657<span style="display: inline-block; color: #99b657; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #99b657 (click to copy)" aria-label="Colour preview: #99b657 (click to copy)" onclick="navigator.clipboard.writeText('#99b657').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #99b657'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground3</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#9f9f9f<span style="display: inline-block; color: #9f9f9f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #9f9f9f (click to copy)" aria-label="Colour preview: #9f9f9f (click to copy)" onclick="navigator.clipboard.writeText('#9f9f9f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #9f9f9f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorCursor.foreground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#9e6a03<span style="display: inline-block; color: #9e6a03; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #9e6a03 (click to copy)" aria-label="Colour preview: #9e6a03 (click to copy)" onclick="navigator.clipboard.writeText('#9e6a03').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #9e6a03'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.findMatchBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#a5d6ff<span style="display: inline-block; color: #a5d6ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #a5d6ff (click to copy)" aria-label="Colour preview: #a5d6ff (click to copy)" onclick="navigator.clipboard.writeText('#a5d6ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #a5d6ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugTokenExpression.string, debugTokenExpression.value</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#b1bac4<span style="display: inline-block; color: #b1bac4; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #b1bac4 (click to copy)" aria-label="Colour preview: #b1bac4 (click to copy)" onclick="navigator.clipboard.writeText('#b1bac4').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #b1bac4'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">terminal.ansiWhite</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#b9ca4a<span style="display: inline-block; color: #b9ca4a; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #b9ca4a (click to copy)" aria-label="Colour preview: #b9ca4a (click to copy)" onclick="navigator.clipboard.writeText('#b9ca4a').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #b9ca4a'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorGutter.addedBackground, scmGraph.foreground5</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#bb8009<span style="display: inline-block; color: #bb8009; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #bb8009 (click to copy)" aria-label="Colour preview: #bb8009 (click to copy)" onclick="navigator.clipboard.writeText('#bb8009').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #bb8009'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>66</td>
<td style="text-align: left;">editor.stackFrameHighlightBackground, peekViewEditor.matchHighlightBackground, peekViewResult.matchHighlightBackground, settings.modifiedItemIndicator</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#bc8cff<span style="display: inline-block; color: #bc8cff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #bc8cff (click to copy)" aria-label="Colour preview: #bc8cff (click to copy)" onclick="navigator.clipboard.writeText('#bc8cff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #bc8cff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsoleInputIcon.foreground, symbolIcon.functionForeground, symbolIcon.methodForeground, terminal.ansiMagenta</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#c397d8<span style="display: inline-block; color: #c397d8; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #c397d8 (click to copy)" aria-label="Colour preview: #c397d8 (click to copy)" onclick="navigator.clipboard.writeText('#c397d8').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #c397d8'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">scmGraph.foreground2</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#c9d1d9<span style="display: inline-block; color: #c9d1d9; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #c9d1d9 (click to copy)" aria-label="Colour preview: #c9d1d9 (click to copy)" onclick="navigator.clipboard.writeText('#c9d1d9').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #c9d1d9'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">button.secondaryForeground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#d29922<span style="display: inline-block; color: #d29922; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #d29922 (click to copy)" aria-label="Colour preview: #d29922 (click to copy)" onclick="navigator.clipboard.writeText('#d29922').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #d29922'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsole.warningForeground, notificationsWarningIcon.foreground, symbolIcon.folderForeground, terminal.ansiYellow</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#d2a8ff<span style="display: inline-block; color: #d2a8ff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #d2a8ff (click to copy)" aria-label="Colour preview: #d2a8ff (click to copy)" onclick="navigator.clipboard.writeText('#d2a8ff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #d2a8ff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.constructorForeground, terminal.ansiBrightMagenta</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#d3a263<span style="display: inline-block; color: #d3a263; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #d3a263 (click to copy)" aria-label="Colour preview: #d3a263 (click to copy)" onclick="navigator.clipboard.writeText('#d3a263').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #d3a263'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground2</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#da3633<span style="display: inline-block; color: #da3633; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #da3633 (click to copy)" aria-label="Colour preview: #da3633 (click to copy)" onclick="navigator.clipboard.writeText('#da3633').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #da3633'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">statusBar.debuggingBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#da3633<span style="display: inline-block; color: #da3633; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #da3633 (click to copy)" aria-label="Colour preview: #da3633 (click to copy)" onclick="navigator.clipboard.writeText('#da3633').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #da3633'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>26</td>
<td style="text-align: left;">diffEditor.removedLineBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#dc91db<span style="display: inline-block; color: #dc91db; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #dc91db (click to copy)" aria-label="Colour preview: #dc91db (click to copy)" onclick="navigator.clipboard.writeText('#dc91db').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #dc91db'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground7</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#dedede<span style="display: inline-block; color: #dedede; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #dedede (click to copy)" aria-label="Colour preview: #dedede (click to copy)" onclick="navigator.clipboard.writeText('#dedede').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #dedede'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editor.foreground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#df5f5f<span style="display: inline-block; color: #df5f5f; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #df5f5f (click to copy)" aria-label="Colour preview: #df5f5f (click to copy)" onclick="navigator.clipboard.writeText('#df5f5f').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #df5f5f'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorError.foreground, gitDecoration.conflictingResourceForeground, gitDecoration.deletedResourceForeground, list.errorForeground, problemsErrorIcon.foreground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#e3b341<span style="display: inline-block; color: #e3b341; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e3b341 (click to copy)" aria-label="Colour preview: #e3b341 (click to copy)" onclick="navigator.clipboard.writeText('#e3b341').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e3b341'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsole.sourceForeground, terminal.ansiBrightYellow</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.foreground, breadcrumb.focusForeground, dropdown.foreground, editorLineNumber.activeForeground, foreground, input.foreground, keybindingLabel.foreground, list.activeSelectionForeground, list.focusForeground, list.hoverForeground, list.inactiveSelectionForeground, notifications.foreground, panelTitle.activeForeground, quickInput.foreground, settings.headerForeground, sideBar.foreground, sideBarSectionHeader.foreground, sideBarTitle.foreground, statusBarItem.remoteForeground, tab.activeForeground, terminal.foreground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>14</td>
<td style="text-align: left;">statusBarItem.hoverBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>1f</td>
<td style="text-align: left;">editorIndentGuide.background, statusBarItem.activeBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#e6edf3<span style="display: inline-block; color: #e6edf3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e6edf3 (click to copy)" aria-label="Colour preview: #e6edf3 (click to copy)" onclick="navigator.clipboard.writeText('#e6edf3').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e6edf3'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>3d</td>
<td style="text-align: left;">editorIndentGuide.activeBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#e78c45<span style="display: inline-block; color: #e78c45; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e78c45 (click to copy)" aria-label="Colour preview: #e78c45 (click to copy)" onclick="navigator.clipboard.writeText('#e78c45').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e78c45'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBar.activeBorder, editorGutter.deletedBackground, panelTitle.activeBorder, scmGraph.foreground3, tab.activeBorderTop</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#e7c547<span style="display: inline-block; color: #e7c547; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #e7c547 (click to copy)" aria-label="Colour preview: #e7c547 (click to copy)" onclick="navigator.clipboard.writeText('#e7c547').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #e7c547'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">scmGraph.foreground4</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#ed90a4<span style="display: inline-block; color: #ed90a4; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ed90a4 (click to copy)" aria-label="Colour preview: #ed90a4 (click to copy)" onclick="navigator.clipboard.writeText('#ed90a4').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ed90a4'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">editorBracketHighlight.foreground1</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#f0883e<span style="display: inline-block; color: #f0883e; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f0883e (click to copy)" aria-label="Colour preview: #f0883e (click to copy)" onclick="navigator.clipboard.writeText('#f0883e').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f0883e'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.arrayForeground, symbolIcon.classForeground, symbolIcon.enumeratorForeground, symbolIcon.fieldForeground, symbolIcon.interfaceForeground, symbolIcon.objectForeground, symbolIcon.packageForeground, symbolIcon.propertyForeground, symbolIcon.structForeground, symbolIcon.variableForeground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#f2cc60<span style="display: inline-block; color: #f2cc60; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f2cc60 (click to copy)" aria-label="Colour preview: #f2cc60 (click to copy)" onclick="navigator.clipboard.writeText('#f2cc60').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f2cc60'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>80</td>
<td style="text-align: left;">editor.findMatchHighlightBackground</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#f85149<span style="display: inline-block; color: #f85149; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #f85149 (click to copy)" aria-label="Colour preview: #f85149 (click to copy)" onclick="navigator.clipboard.writeText('#f85149').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #f85149'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugIcon.breakpointForeground, errorForeground, notificationsErrorIcon.foreground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#ff7b72<span style="display: inline-block; color: #ff7b72; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ff7b72 (click to copy)" aria-label="Colour preview: #ff7b72 (click to copy)" onclick="navigator.clipboard.writeText('#ff7b72').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ff7b72'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">symbolIcon.keywordForeground, symbolIcon.moduleForeground, symbolIcon.namespaceForeground, terminal.ansiRed</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#ff7b72<span style="display: inline-block; color: #ff7b72; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ff7b72 (click to copy)" aria-label="Colour preview: #ff7b72 (click to copy)" onclick="navigator.clipboard.writeText('#ff7b72').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ff7b72'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span>4d</td>
<td style="text-align: left;">diffEditor.removedTextBackground</td>
</tr>
<tr class="even">
<td style="text-align: left; width: 12em;">#ffa198<span style="display: inline-block; color: #ffa198; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ffa198 (click to copy)" aria-label="Colour preview: #ffa198 (click to copy)" onclick="navigator.clipboard.writeText('#ffa198').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ffa198'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">debugConsole.errorForeground, debugTokenExpression.error, terminal.ansiBrightRed</td>
</tr>
<tr class="odd">
<td style="text-align: left; width: 12em;">#ffffff<span style="display: inline-block; color: #ffffff; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; position: relative;" title="Colour preview: #ffffff (click to copy)" aria-label="Colour preview: #ffffff (click to copy)" onclick="navigator.clipboard.writeText('#ffffff').then(() => { const span = this; const originalTitle = span.title; span.title = 'Copied: #ffffff'; let tooltip = document.createElement('div'); tooltip.textContent = 'Copied!'; tooltip.style.cssText = 'position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;font-family:sans-serif;white-space:nowrap;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.3);pointer-events:none;'; span.appendChild(tooltip); setTimeout(() => { span.title = originalTitle; if (span.contains(tooltip)) span.removeChild(tooltip); }, 1500); }).catch(() => console.error('Failed to copy colour code'));">◉</span></td>
<td style="text-align: left;">activityBarBadge.foreground, badge.foreground, button.foreground, statusBar.debuggingForeground, terminal.ansiBrightWhite</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="fin-tomorrow-night-bright-r-classic" class="level2">
<h2 class="anchored" data-anchor-id="fin-tomorrow-night-bright-r-classic">Fin: Tomorrow Night Bright (R Classic)</h2>
<p>Once the <code>tomorrow-night-bright-r-classic.json</code> file was ready, then it was time to publish the theme to the VS Code Extension Marketplace and then the Open VSX Registry. We added some resources on how to do this below. With that, the Tomorrow Night Bright (R Classic) theme is available to the world!</p>
<p><img src="https://ivelasq.rbind.io/blog/positron-theme/images/8-installation.png" class="img-fluid"></p>
<p>Like any other open-source project, this is just the beginning! We’ve optimized the theme for R scripts and many key workbench elements, but there’s more to do. Our next steps will be to optimize the theme for Python scripts, JSON files, and other files supported by RStudio — so those migrating from RStudio to Positron will feel at home in Tomorrow Night Bright. We welcome you to submit a <a href="https://github.com/gvelasq/tomorrow-night-bright-r-classic">pull request in the GitHub repository</a> if you’d like to make a contribution or use the files as a reference if you want to create your own Positron theme!</p>
</section>
<section id="installing-tomorrow-night-bright-r-classic" class="level2">
<h2 class="anchored" data-anchor-id="installing-tomorrow-night-bright-r-classic">Installing Tomorrow Night Bright (R Classic)</h2>
<p>To install the theme in Positron, navigate to the Extensions marketplace by:</p>
<ul>
<li>Typing <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> to access the Command Palette and searching for <code>Extensions: Install Extensions</code>,</li>
<li>Typing the Extensions shortcut <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>X</kbd>,</li>
<li>Or, clicking the <img src="https://ivelasq.rbind.io/blog/positron-theme/images/9-positron_sidebar_extensions.png" style="width:20px;height:20px;"> button on the left sidebar in Positron.</li>
</ul>
<p>Search for ‘Tomorrow Night Bright (R Classic)’ and then click Install. Tada 🎉 you now have our theme installed. We hope you enjoy it!</p>
</section>
<section id="more-resources" class="level2">
<h2 class="anchored" data-anchor-id="more-resources">More resources</h2>
<p>The process of building and publishing an extension can be quite involved! We found these links to be particularly helpful:</p>
<ul>
<li><a href="https://code.visualstudio.com/api/get-started/your-first-extension">VS Code: Your First Extension</a>: This is a primer on how to build an extension from first principles.</li>
<li><a href="https://code.visualstudio.com/api/extension-guides/color-theme">VS Code: Color Theme</a>: This is a primer on how to build color theme extensions, and how color theme extensions are structured.</li>
<li><a href="https://code.visualstudio.com/api/references/theme-color">VS Code: Theme Color</a>: This is comprehensive documentation on all color settings available in VS Code.</li>
<li><a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension">VS Code: Publishing Extensions</a>: This is a tutorial on how to publish an extension on the VS Code Extension Marketplace.</li>
<li><a href="https://code.visualstudio.com/api/references/extension-manifest">VS Code: Extension Manifest</a>: This is detailed documentation on the <code>package.json</code> file in the root folder of all extensions, also known as the ‘extension manifest’ or ‘manifest.’ Our extension’s <a href="https://github.com/gvelasq/tomorrow-night-bright-r-classic/blob/main/package.json"><code>package.json</code></a> may be helpful for reference. N.B., the Yeoman utility generates only a bare-bones <code>package.json</code>, but to publish your extension online you’ll need to add a publisher field and more. You will also need to add a <a href="https://github.com/gvelasq/tomorrow-night-bright-r-classic/blob/main/package-lock.json"><code>package-lock.json</code></a> file!</li>
<li><a href="https://github.com/EclipseFdn/open-vsx.org/wiki/Publishing-Extensions">Open VSX: Publishing Extensions</a>: This is documentation on how to publish an extension to the Open VSX Registry.</li>
<li><a href="https://github.com/HaaLeo/publish-vscode-extension/tree/master#readme">HaaLeo/publish-vscode-extension</a>: This is a very helpful GitHub Action, recommended by the Open VSX documentation, that automates publishing your extension in the VS Code Extension Marketplace and the Open VSX Registry. We lightly modified this GitHub Action in our extension: <a href="https://github.com/gvelasq/tomorrow-night-bright-r-classic/blob/main/.github/workflows/publish-extension.yaml"><code>publish-extension.yaml</code></a>.</li>
</ul>
<p>Thanks to <a href="https://github.com/mcanouil">Mickaël Canouil</a>’s Quarto extension, <a href="https://github.com/mcanouil/quarto-preview-colour/">Preview Color</a>, which allowed us to display colors associated with hex codes in this blog post.</p>
<hr>
</section>
<section id="comments" class="level2 unlisted">
<h2 class="unlisted anchored" data-anchor-id="comments">Comments</h2>
<bluesky-comments-section post="https://bsky.app/profile/ivelasq3.bsky.social/post/3lq5senxpbk27"></bluesky-comments-section>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p><code>brew install –-cask r</code>, <code>brew install –-cask rstudio</code>, <code>brew install –-cask positron</code> will get you up and running quickly with Homebrew on macOS. Check out our <a href="https://github.com/gvelasq/dotfiles/tree/main/macos">recommended MacOS configuration</a>.↩︎</p></li>
<li id="fn2"><p>Shoutout to <a href="https://fs.r-lib.org">{fs}</a> for being an <a href="https://blog.djnavarro.net/posts/2024-10-06_fs">outstanding</a> R package and <code>fs::dir_tree()</code> in particular!↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/positron-theme/</guid>
  <pubDate>Tue, 27 May 2025 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/positron-theme/img/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Quarto dashboard creation and automation</title>
  <link>https://ivelasq.rbind.io/blog/automated-quarto-dashboard/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/automated-quarto-dashboard/img/thumbnail-wide.jpg" class="img-fluid figure-img" alt="A young woman pinning something red on her green dress."></p>
<figcaption>John White Alexander, Study in Black and Green</figcaption>
</figure>
</div>
<p>I had the opportunity to present an <a href="https://youtu.be/xnJuXOw7iu8?feature=shared">automated Quarto dashboard on Posit’s Monthly End-to-End Workflow with Posit Team</a>, followed by a <a href="https://www.youtube.com/watch?v=d21PQyOGlgY">Q&amp;A</a>. The project involved a script that retrieves <a href="https://www.bls.gov/cpi/">Consumer Price Index (CPI)</a> data from the Bureau of Labor Statistics (BLS) API, processes and cleans the data, and saves it as a pin using the <a href="https://pypi.org/project/pins/">{pins} package</a> to <a href="https://posit.co/products/enterprise/connect/">Posit Connect</a><sup>1</sup>. A <code>.qmd</code> file then reads the pinned data and generates a Quarto dashboard, which is deployed to Posit Connect. Both the script and the <code>.qmd</code> file are scheduled to run monthly on Posit Connect, ensuring the pin and dashboard always reflect the latest data from the BLS. You can watch the recording here:</p>
<center>
<iframe width="560" height="315" src="https://www.youtube.com/embed/xnJuXOw7iu8?si=M01jrFbKLeCr6GyB" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="">
</iframe>
</center>
<p>The workflow was implemented in Python, and one of the most common questions I received was, “Can I do this in R?” The answer is: absolutely! A key advantage of the tools used in this workflow is their multilingualism or the availability of equivalent tools in both R and Python.</p>
<ul>
<li>The {pins} package is available in both R and Python.</li>
<li>Quarto is independent of the computational environment and can be run with either a knitr engine (for R) or a Jupyter engine (for Python).</li>
<li>Posit Connect supports hosting data products created in both R and Python.</li>
</ul>
<p>This blog post will guide you through the equivalent workflow in R, which can be found in this <a href="https://github.com/ivelasq/inflation-explorer">repository</a>. If you’re interested in the Python version, you can explore it in this <a href="https://github.com/posit-marketing/inflation-explorer">repository</a>.</p>
<p>This post features Posit Connect heavily, but there are other tools available. For example, I’ve written a blog post on creating an automated dashboard using {flexdashboard} and GitHub Actions, which you can check out <a href="https://ivelasq.rbind.io/blog/automated-youtube-dashboard/">here</a>.</p>
<section id="before-we-begin-quarto-dashboards" class="level2">
<h2 class="anchored" data-anchor-id="before-we-begin-quarto-dashboards">Before we begin… Quarto dashboards?!</h2>
<p>That’s right! With version 1.4, Quarto now supports dashboards — a new output format for easily creating dashboards from notebooks in R, Python, or Julia. You can include plots, tables, value boxes, and text, and deploy your dashboards as static web pages (no special server needed). For enhanced interactivity, you can integrate a backend Shiny server. You can also customize the appearance by adding a Bootstrap theme or custom Sass elements.</p>
<p>To learn more about creating dashboards, check out the <a href="https://quarto.org/docs/dashboards/">Quarto documentation</a> or watch my <a href="https://ivelasq.rbind.io/talk/quarto-dashboards/">R-Ladies Rome Quarto Dashboards talk</a>.</p>
</section>
<section id="consumer-price-index-cpi-data" class="level2">
<h2 class="anchored" data-anchor-id="consumer-price-index-cpi-data">Consumer Price Index (CPI) data</h2>
<p>This dashboard uses the Consumer Price Index (CPI) data from the Bureau of Labor Statistics (BLS). The CPI monitors changes in the prices of a basket of goods over time, covering a range of categories, and is updated monthly. The dashboard automatically refreshes each month when the latest BLS data is released.</p>
</section>
<section id="setup" class="level2">
<h2 class="anchored" data-anchor-id="setup">Setup</h2>
<p>To open the project in RStudio, navigate to File &gt; New Project &gt; Version Control and paste the following URL: https://github.com/ivelasq/inflation-explorer.git.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/automated-quarto-dashboard/images/clone-r.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:50.0%"></p>
</figure>
</div>
<p>The files in the project include:</p>
<pre><code>├── images
│   └── logo.png            # Logo image to use in the dashboard
├── .gitignore              # Files and folders to ignore when pushing up changes
├── README.md               # Project overview and setup instructions
├── _publish.yml            # File for specifying the publishing destination
├── _quarto.yml             # Quarto project configuration file
├── all_data_report.json    # JSON version of the downloaded BLS data
├── custom.scss             # Custom Sass file
├── index.qmd               # Quarto dashboard document
└── script.R                # R script version of the ETL script</code></pre>
<section id="virtual-environments" class="level3">
<h3 class="anchored" data-anchor-id="virtual-environments">Virtual environments</h3>
<p>In the Python version of this demo, I created a virtual environment. Virtual environments are commonly used to manage dependencies and isolate project-specific packages. In R, using virtual environments is less common. R installs packages either system-wide or in user-specific library paths. If you are an RStudio Projects user, the project-specific settings manage your dependencies. And in general, R’s package management system is more flexible with handling packages. However, the <a href="https://rstudio.github.io/renv/">{renv} package</a> provides similar functionality to Python’s virtual environments by managing project-specific dependencies and package versions.</p>
</section>
<section id="environment-variables" class="level3">
<h3 class="anchored" data-anchor-id="environment-variables">Environment variables</h3>
<p>Environment variables are variables that are needed for code but should not be publicly shared. This project has three:</p>
<ol type="1">
<li><code>BLS_KEY</code>: A BLS API access token, obtained at <a href="https://www.bls.gov/developers/home.htm" class="uri">https://www.bls.gov/developers/home.htm</a>.</li>
<li><code>CONNECT_SERVER</code>: The URL for the Connect server.</li>
<li><code>CONNECT_API_KEY</code>: The access key for the Connect server.</li>
</ol>
<p>To store these variables in your R environment (<code>.Renviron</code>), you can use <code>Sys.setenv()</code> in your Terminal:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Terminal</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" data-filename="Terminal" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Sys.setenv</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">CONNECT_API_KEY</span> = <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"connect api key here"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>Or, you can edit your <code>.Renviron</code> file using the {usethis} package. Run <code>usethis::edit_r_environ()</code> to open the .Renviron file and add the variables manually.</p>
</section>
</section>
<section id="extract-transform-load-process" class="level2">
<h2 class="anchored" data-anchor-id="extract-transform-load-process">Extract-transform-load process</h2>
<p>We use a script to pull raw data from the BLS API, clean it for use in our dashboard, and then save it as a pin. This process, known as Extract-Transform-Load (ETL), is executed in the <code>script.R</code> file:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>script.R</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="annotated-cell-3" data-filename="script.R" style="background: #f1f3f5;"><pre class="sourceCode r code-annotation-code code-with-copy code-annotated"><code class="sourceCode r"><span id="annotated-cell-3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' ---</span></span>
<span id="annotated-cell-3-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' title: "R script file"</span></span>
<span id="annotated-cell-3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' ---</span></span>
<span id="annotated-cell-3-4"></span>
<span id="annotated-cell-3-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(httr2)</span>
<span id="annotated-cell-3-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(jsonlite)</span>
<span id="annotated-cell-3-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="1">1</button><span id="annotated-cell-3-8" class="code-annotation-target"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(pins)</span>
<span id="annotated-cell-3-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyr)</span>
<span id="annotated-cell-3-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(purrr)</span>
<span id="annotated-cell-3-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(lubridate)</span>
<span id="annotated-cell-3-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(stringr)</span>
<span id="annotated-cell-3-13"></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="2">2</button><span id="annotated-cell-3-14" class="code-annotation-target"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Environment variables</span></span>
<span id="annotated-cell-3-15"></span>
<span id="annotated-cell-3-16">bls_key <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Sys.getenv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BLS_KEY"</span>)</span>
<span id="annotated-cell-3-17">connect_server <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Sys.getenv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CONNECT_SERVER"</span>)</span>
<span id="annotated-cell-3-18">connect_api_key <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Sys.getenv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CONNECT_API_KEY"</span>)</span>
<span id="annotated-cell-3-19"></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="3">3</button><span id="annotated-cell-3-20" class="code-annotation-target"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># BLS tables</span></span>
<span id="annotated-cell-3-21"></span>
<span id="annotated-cell-3-22">table_ids <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="annotated-cell-3-23">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SA0"</span>,</span>
<span id="annotated-cell-3-24">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SA0L1E"</span>,</span>
<span id="annotated-cell-3-25">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SAF1"</span>,</span>
<span id="annotated-cell-3-26">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SA0E"</span>,</span>
<span id="annotated-cell-3-27">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SETB01"</span>,</span>
<span id="annotated-cell-3-28">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SAM"</span>,</span>
<span id="annotated-cell-3-29">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SEMC01"</span>,</span>
<span id="annotated-cell-3-30">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SEMD01"</span>,</span>
<span id="annotated-cell-3-31">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SEMF01"</span>,</span>
<span id="annotated-cell-3-32">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SAH1"</span></span>
<span id="annotated-cell-3-33">)</span>
<span id="annotated-cell-3-34"></span>
<span id="annotated-cell-3-35">id_to_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;">c</span>(</span>
<span id="annotated-cell-3-36">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SA0"</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;">"All groups CPI"</span>,</span>
<span id="annotated-cell-3-37">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SA0L1E"</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;">"All items less food and energy"</span>,</span>
<span id="annotated-cell-3-38">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SAF1"</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;">"Food"</span>,</span>
<span id="annotated-cell-3-39">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SA0E"</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;">"Energy"</span>,</span>
<span id="annotated-cell-3-40">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SETB01"</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;">"Gasoline"</span>,</span>
<span id="annotated-cell-3-41">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SAM"</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;">"Medical care"</span>,</span>
<span id="annotated-cell-3-42">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SEMC01"</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;">"Physicians' services"</span>,</span>
<span id="annotated-cell-3-43">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SEMD01"</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;">"Hospital services"</span>,</span>
<span id="annotated-cell-3-44">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SEMF01"</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;">"Prescription drugs"</span>,</span>
<span id="annotated-cell-3-45">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CUUR0000SAH1"</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;">"Shelter"</span></span>
<span id="annotated-cell-3-46">)</span>
<span id="annotated-cell-3-47"></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="4">4</button><span id="annotated-cell-3-48" class="code-annotation-target"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pull BLS API data</span></span>
<span id="annotated-cell-3-49"></span>
<span id="annotated-cell-3-50">get_bls_data <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>(parameters) {</span>
<span id="annotated-cell-3-51">  response <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">request</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://api.bls.gov/publicAPI/v2/timeseries/data/"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-52">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">req_headers</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Content-Type"</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;">"application/json"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-53">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">req_body_json</span>(parameters, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">auto_unbox =</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="annotated-cell-3-54">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">req_perform</span>()</span>
<span id="annotated-cell-3-55">  </span>
<span id="annotated-cell-3-56">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resp_status</span>(response) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>) {</span>
<span id="annotated-cell-3-57">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stop</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"API Error:"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resp_status</span>(response)))</span>
<span id="annotated-cell-3-58">  }</span>
<span id="annotated-cell-3-59">  </span>
<span id="annotated-cell-3-60">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resp_body_json</span>(response))</span>
<span id="annotated-cell-3-61">}</span>
<span id="annotated-cell-3-62"></span>
<span id="annotated-cell-3-63">all_data <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>()</span>
<span id="annotated-cell-3-64"></span>
<span id="annotated-cell-3-65"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (table_id <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> table_ids) {</span>
<span id="annotated-cell-3-66">  parameters <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="annotated-cell-3-67">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">registrationkey =</span> bls_key,</span>
<span id="annotated-cell-3-68">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seriesid =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(table_id),</span>
<span id="annotated-cell-3-69">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">startyear =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2018"</span>,</span>
<span id="annotated-cell-3-70">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">endyear =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2024"</span>,</span>
<span id="annotated-cell-3-71">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">calculations =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="annotated-cell-3-72">  )</span>
<span id="annotated-cell-3-73">  </span>
<span id="annotated-cell-3-74">  bls_data_object <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">get_bls_data</span>(parameters)</span>
<span id="annotated-cell-3-75">  all_data[[table_id]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> bls_data_object</span>
<span id="annotated-cell-3-76">}</span>
<span id="annotated-cell-3-77"></span>
<span id="annotated-cell-3-78">file_path <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file.path</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getwd</span>(), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"all_data_report.json"</span>)</span>
<span id="annotated-cell-3-79"></span>
<span id="annotated-cell-3-80"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write_json</span>(all_data, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">path =</span> file_path, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pretty =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="annotated-cell-3-81"></span>
<span id="annotated-cell-3-82">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fromJSON</span>(file_path)</span>
<span id="annotated-cell-3-83"></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="5">5</button><span id="annotated-cell-3-84" class="code-annotation-target"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Clean data</span></span>
<span id="annotated-cell-3-85"></span>
<span id="annotated-cell-3-86">series_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-87">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>( <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> .x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Results<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>series) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-88">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</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;">tibble</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seriesID =</span> .x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>seriesID, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> .x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>data)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> </span>
<span id="annotated-cell-3-89">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list_rbind</span>()</span>
<span id="annotated-cell-3-90"></span>
<span id="annotated-cell-3-91">combined_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> series_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-92">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unnest</span>(data)</span>
<span id="annotated-cell-3-93"></span>
<span id="annotated-cell-3-94">clean_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> combined_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-95">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="annotated-cell-3-96">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">year_month =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ymd</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(year, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_sub</span>(period, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"01"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-"</span>)),</span>
<span id="annotated-cell-3-97">    <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;">as.numeric</span>(value),</span>
<span id="annotated-cell-3-98">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seriesID =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(seriesID),</span>
<span id="annotated-cell-3-99">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">category_label =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">recode</span>(seriesID, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!!!</span>id_to_label)</span>
<span id="annotated-cell-3-100">  )</span>
<span id="annotated-cell-3-101"></span>
<span id="annotated-cell-3-102">january_2018_values <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> clean_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-103">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(year_month <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ymd</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2018-01-01"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-104">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(seriesID, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">jan_2018_value =</span> value) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-105">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct</span>()</span>
<span id="annotated-cell-3-106"></span>
<span id="annotated-cell-3-107">joined_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> clean_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-108">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">left_join</span>(january_2018_values, <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;">"seriesID"</span>)</span>
<span id="annotated-cell-3-109"></span>
<span id="annotated-cell-3-110">final_cpi_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> joined_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-111">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="annotated-cell-3-112">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">jan_2018_diff =</span> value <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> jan_2018_value,</span>
<span id="annotated-cell-3-113">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">jan_2018_pct_change =</span> (jan_2018_diff <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> jan_2018_value) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="annotated-cell-3-114">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-115">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrange</span>(year_month) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-3-116">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">percent_change_from_previous_month =</span> (value <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lag</span>(value) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="annotated-cell-3-117">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.by =</span> category_label)</span>
<span id="annotated-cell-3-118"></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="6">6</button><span id="annotated-cell-3-119" class="code-annotation-target"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pin data to Connect</span></span>
<span id="annotated-cell-3-120"></span>
<span id="annotated-cell-3-121">board <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">board_connect</span>()</span>
<span id="annotated-cell-3-122"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pin_write</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">board =</span> board, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"isabella.velasquez/bls-cpi-data"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> final_cpi_dat)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</div>
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-3" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="8" data-code-annotation="1">The {pins} package allows you to pin data, models, or other objects for easy access or sharing. Pins are ideal for ephemeral, ever-changing data that needs to be referenced but does not require a database.</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="14" data-code-annotation="2">We load the environment variables configured earlier.</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="20" data-code-annotation="3">Next, we define the list of BLS tables containing the data we want to display on the dashboard.</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="4">4</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="48" data-code-annotation="4">A function then pulls this data into R.</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="5">5</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="84" data-code-annotation="5">This is followed by a series of data cleaning and transformation steps.</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="6">6</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="119" data-code-annotation="6">Finally, we configure our Posit Connect server<sup>2</sup> and write the pin to Connect. <a href="https://pub.demo.posit.team/public/inflation-explorer-pin/">Access the pin here</a>.</span>
</dd>
</dl>
<p>Posit Connect supports rendering script files (e.g., <code>.py</code> or <code>.R</code>). Once deployed to Connect, these scripts can be scheduled for automatic refresh and their output can be emailed, similar to other content on Connect. For more details, refer to the <a href="https://docs.posit.co/connect/user/scripts/">Scripts documentation</a>.</p>
<p>To publish <code>script.R</code> to Connect, run the following command:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Terminal</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" data-filename="Terminal" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">rsconnect::deployApp</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">appFiles</span> = <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"script.R"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>This is the content owner view of the deployed script. You can configure it to update daily at 11 PM PT using the configuration pane.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/automated-quarto-dashboard/images/configure-schedule.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:70.0%"></p>
</figure>
</div>
<p><a href="https://pub.demo.posit.team/public/inflation-explorer-etl-script/">View the deployed script here</a>.</p>
</section>
<section id="creating-a-quarto-dashboard" class="level2">
<h2 class="anchored" data-anchor-id="creating-a-quarto-dashboard">Creating a Quarto dashboard</h2>
<p>Now, we can move on to actually creating a Quarto dashboard!</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>index.qmd</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="annotated-cell-5" data-filename="index.qmd" style="background: #f1f3f5;"><pre class="sourceCode markdown md code-annotation-code code-with-copy code-annotated"><code class="sourceCode markdown"><span id="annotated-cell-5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span></span>
<span id="annotated-cell-5-2"><span class="an" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">title:</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> "Inflation explorer: showing the change in price for various goods and services"</span></span>
<span id="annotated-cell-5-3"><span class="an" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">format:</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="1">1</button><span id="annotated-cell-5-4" class="code-annotation-target"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  dashboard:</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="2">2</button><span id="annotated-cell-5-5" class="code-annotation-target"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    logo: images/logo.png</span></span>
<span id="annotated-cell-5-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    nav-buttons:</span></span>
<span id="annotated-cell-5-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    - icon: github</span></span>
<span id="annotated-cell-5-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">      href: "https://github.com/ivelasq/inflation-explorer"</span></span>
<span id="annotated-cell-5-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    theme:</span></span>
<span id="annotated-cell-5-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    - pulse</span></span>
<span id="annotated-cell-5-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    - custom.scss</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="3">3</button><span id="annotated-cell-5-12" class="code-annotation-target"><span class="an" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">resource_files:</span></span>
<span id="annotated-cell-5-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">- custom.scss</span></span>
<span id="annotated-cell-5-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">- images/logo.png</span></span>
<span id="annotated-cell-5-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span></span>
<span id="annotated-cell-5-16"></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="4">4</button><span id="annotated-cell-5-17" class="code-annotation-target"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="annotated-cell-5-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| label: setup</span></span>
<span id="annotated-cell-5-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| include: false</span></span>
<span id="annotated-cell-5-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(pins)</span>
<span id="annotated-cell-5-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(lubridate)</span>
<span id="annotated-cell-5-22"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="annotated-cell-5-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyr)</span>
<span id="annotated-cell-5-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="annotated-cell-5-25"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(RColorBrewer)</span>
<span id="annotated-cell-5-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(gt)</span>
<span id="annotated-cell-5-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(plotly)</span>
<span id="annotated-cell-5-28"></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="5">5</button><span id="annotated-cell-5-29" class="code-annotation-target">board <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="annotated-cell-5-30">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">board_connect</span>(</span>
<span id="annotated-cell-5-31">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">auth =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"manual"</span>,</span>
<span id="annotated-cell-5-32">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">server =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://pub.demo.posit.team/"</span>,</span>
<span id="annotated-cell-5-33">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">key =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Sys.getenv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CONNECT_API_KEY"</span>)</span>
<span id="annotated-cell-5-34">  )</span>
<span id="annotated-cell-5-35"></span>
<span id="annotated-cell-5-36">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="annotated-cell-5-37">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pin_read</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">board =</span> board, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"isabella.velasquez/bls-cpi-data"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-5-38">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">year_month =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(year_month, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">format =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%Y-%m-%d"</span>))</span>
<span id="annotated-cell-5-39"></span>
<span id="annotated-cell-5-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Value for last updated date</span></span>
<span id="annotated-cell-5-41">last_updated_date <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-5-42">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">last_updated_date =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(year_month)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-5-43">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull</span>(last_updated_date)</span>
<span id="annotated-cell-5-44"></span>
<span id="annotated-cell-5-45"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Value for the percentage change from the previous month</span></span>
<span id="annotated-cell-5-46">cpi_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> </span>
<span id="annotated-cell-5-47">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(seriesID <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;">"CUUR0000SA0"</span>)</span>
<span id="annotated-cell-5-48"></span>
<span id="annotated-cell-5-49">latest_cpi_value <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cpi_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-5-50">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">latest_value =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">last</span>(value)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-5-51">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull</span>(latest_value)</span>
<span id="annotated-cell-5-52"></span>
<span id="annotated-cell-5-53">latest_cpi_percent_change <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cpi_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-5-54">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(year_month <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> last_updated_date) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-5-55">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull</span>(jan_2018_pct_change)</span>
<span id="annotated-cell-5-56"></span>
<span id="annotated-cell-5-57"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Data for table</span></span>
<span id="annotated-cell-5-58">pivot_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> </span>
<span id="annotated-cell-5-59">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(category_label, year_month, percent_change_from_previous_month) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="annotated-cell-5-60">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_wider</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_from =</span> year_month, </span>
<span id="annotated-cell-5-61">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_from =</span> percent_change_from_previous_month) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-5-62">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(category_label, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tail</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(.), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> </span>
<span id="annotated-cell-5-63">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrange</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">desc</span>(category_label))</span>
<span id="annotated-cell-5-64"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="annotated-cell-5-65"></span>
<span id="annotated-cell-5-66"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">## Row {height=20%}</span></span>
<span id="annotated-cell-5-67"></span>
<span id="annotated-cell-5-68"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r} </span></span>
<span id="annotated-cell-5-69"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| label: valuebox1</span></span>
<span id="annotated-cell-5-70"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| content: valuebox</span></span>
<span id="annotated-cell-5-71"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| title: "Last updated"</span></span>
<span id="annotated-cell-5-72"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| color: #fff</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="6">6</button><span id="annotated-cell-5-73" class="code-annotation-target">last_updated_date</span>
<span id="annotated-cell-5-74"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="annotated-cell-5-75"></span>
<span id="annotated-cell-5-76"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r} </span></span>
<span id="annotated-cell-5-77"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| label: valuebox2</span></span>
<span id="annotated-cell-5-78"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| content: valuebox</span></span>
<span id="annotated-cell-5-79"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| title: "Consumer Price Index (CPI)"</span></span>
<span id="annotated-cell-5-80"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| icon: basket</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="7">7</button><span id="annotated-cell-5-81" class="code-annotation-target"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="annotated-cell-5-82">  <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;">round</span>(latest_cpi_value, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="annotated-cell-5-83">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">icon =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"basket"</span>,</span>
<span id="annotated-cell-5-84">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"primary"</span></span>
<span id="annotated-cell-5-85">)</span>
<span id="annotated-cell-5-86"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="annotated-cell-5-87"></span>
<span id="annotated-cell-5-88"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="annotated-cell-5-89"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| label: valuebox3</span></span>
<span id="annotated-cell-5-90"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| content: valuebox</span></span>
<span id="annotated-cell-5-91"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| title: "Increase from previous month"</span></span>
<span id="annotated-cell-5-92"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| icon: percent</span></span>
<span id="annotated-cell-5-93"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| color: primary</span></span>
<span id="annotated-cell-5-94">value <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(latest_cpi_percent_change, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="annotated-cell-5-95"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="annotated-cell-5-96"></span>
<span id="annotated-cell-5-97"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">## Row {height=80%}</span></span>
<span id="annotated-cell-5-98"></span>
<span id="annotated-cell-5-99"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">### Column {width=20%}</span></span>
<span id="annotated-cell-5-100"></span>
<span id="annotated-cell-5-101">The **Consumer Price Index (CPI)** is a measure of the average change over time in the prices paid by urban consumers for a market basket of consumer goods and services. </span>
<span id="annotated-cell-5-102"></span>
<span id="annotated-cell-5-103">Indexes are available for the U.S. and various geographic areas. Average price data for select utility, automotive fuel, and food items are also available.</span>
<span id="annotated-cell-5-104"></span>
<span id="annotated-cell-5-105">**Source: Bureau of Labor Statistics**</span>
<span id="annotated-cell-5-106"></span>
<span id="annotated-cell-5-107"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">### Column {.tabset width=80%}</span></span>
<span id="annotated-cell-5-108"></span>
<span id="annotated-cell-5-109"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="annotated-cell-5-110"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| label: pct-change-jan-2018-code</span></span>
<span id="annotated-cell-5-111"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| include: false</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="8">8</button><span id="annotated-cell-5-112" class="code-annotation-target">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-5-113">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrange</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">desc</span>(category_label), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">desc</span>(year_month))</span>
<span id="annotated-cell-5-114"></span>
<span id="annotated-cell-5-115">p1 <span class="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>(df,             </span>
<span id="annotated-cell-5-116">             <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> year_month, </span>
<span id="annotated-cell-5-117">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> jan_2018_pct_change, </span>
<span id="annotated-cell-5-118">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> category_label,</span>
<span id="annotated-cell-5-119">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> category_label)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="annotated-cell-5-120">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> category_label)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="annotated-cell-5-121">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_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;">ifelse</span>(df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>category_label <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;">"All groups CPI"</span>,</span>
<span id="annotated-cell-5-122">                                     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#765AAF"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#765AAF"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="annotated-cell-5-123">  <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="annotated-cell-5-124">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="annotated-cell-5-125">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.title.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="annotated-cell-5-126">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.title.y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="annotated-cell-5-127">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>),</span>
<span id="annotated-cell-5-128">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.y =</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;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>)</span>
<span id="annotated-cell-5-129">    )</span>
<span id="annotated-cell-5-130"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="annotated-cell-5-131"></span>
<span id="annotated-cell-5-132">::: {.card title="Percentage change since Jan 2018"}</span>
<span id="annotated-cell-5-133"></span>
<span id="annotated-cell-5-134">Use this inflation data explorer to see which goods and services are getting cheaper or more expensive in the U.S.</span>
<span id="annotated-cell-5-135"></span>
<span id="annotated-cell-5-136"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="annotated-cell-5-137"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| fig-width: 20</span></span>
<span id="annotated-cell-5-138"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| fig-height: 8</span></span>
<span id="annotated-cell-5-139"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplotly</span>(p1)</span>
<span id="annotated-cell-5-140"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="annotated-cell-5-141">:::</span>
<span id="annotated-cell-5-142"></span>
<span id="annotated-cell-5-143"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="annotated-cell-5-144"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| label: pct-change-monthly-code</span></span>
<span id="annotated-cell-5-145"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| include: false</span></span>
<span id="annotated-cell-5-146">latest_month_data <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-5-147">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(year_month <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(year_month)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-5-148">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrange</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">desc</span>(percent_change_from_previous_month))</span>
<span id="annotated-cell-5-149"></span>
<span id="annotated-cell-5-150">top_six_categories <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> latest_month_data <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-5-151">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">slice_head</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)</span>
<span id="annotated-cell-5-152"></span>
<span id="annotated-cell-5-153">p2 <span class="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>(</span>
<span id="annotated-cell-5-154">  top_six_categories,</span>
<span id="annotated-cell-5-155">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(</span>
<span id="annotated-cell-5-156">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reorder</span>(category_label, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>percent_change_from_previous_month),</span>
<span id="annotated-cell-5-157">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> percent_change_from_previous_month,</span>
<span id="annotated-cell-5-158">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> category_label</span>
<span id="annotated-cell-5-159">  )</span>
<span id="annotated-cell-5-160">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="annotated-cell-5-161">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_bar</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stat =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"identity"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="annotated-cell-5-162">  <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;">rev</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colorRampPalette</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">brewer.pal</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BuPu"</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>
<span id="annotated-cell-5-163">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</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;">"Percent Change"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="annotated-cell-5-164">  <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="annotated-cell-5-165">  <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="annotated-cell-5-166">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="annotated-cell-5-167">    <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;">"none"</span>,</span>
<span id="annotated-cell-5-168">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">24</span>),</span>
<span id="annotated-cell-5-169">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.title.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>),</span>
<span id="annotated-cell-5-170">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.y =</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;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">24</span>)</span>
<span id="annotated-cell-5-171">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="annotated-cell-5-172">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_flip</span>()</span>
<span id="annotated-cell-5-173"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="annotated-cell-5-174"></span>
<span id="annotated-cell-5-175">::: {.card title="Last month's top 6"}</span>
<span id="annotated-cell-5-176">Percentage change in CPI by category for the last month, top six categories</span>
<span id="annotated-cell-5-177"></span>
<span id="annotated-cell-5-178"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="annotated-cell-5-179"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| fig-width: 18</span></span>
<span id="annotated-cell-5-180"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| fig-height: 8</span></span>
<span id="annotated-cell-5-181">p2</span>
<span id="annotated-cell-5-182"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="annotated-cell-5-183">:::</span>
<span id="annotated-cell-5-184"></span>
<span id="annotated-cell-5-185"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="annotated-cell-5-186"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| label: pct-change-monthly-table</span></span>
<span id="annotated-cell-5-187"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| title: "Monthly changes in prices"</span></span>
<span id="annotated-cell-5-188"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(pivot_df)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Category"</span> </span>
<span id="annotated-cell-5-189"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(pivot_df)[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ymd</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(pivot_df)[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%B %Y"</span>)</span>
<span id="annotated-cell-5-190"></span>
<span id="annotated-cell-5-191">pivot_gt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pivot_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="9">9</button><span id="annotated-cell-5-192" class="code-annotation-target">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gt</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-5-193">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tab_header</span>(</span>
<span id="annotated-cell-5-194">    <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;">"Monthly Percent Change by Category"</span>,</span>
<span id="annotated-cell-5-195">    <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;">"Last four months"</span></span>
<span id="annotated-cell-5-196">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-5-197">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_number</span>(</span>
<span id="annotated-cell-5-198">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">columns =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,</span>
<span id="annotated-cell-5-199">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">decimals =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="annotated-cell-5-200">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-5-201">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tab_style</span>(</span>
<span id="annotated-cell-5-202">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">style =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cell_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">weight =</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;">align =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"center"</span>),</span>
<span id="annotated-cell-5-203">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">locations =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cells_column_labels</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">everything</span>())</span>
<span id="annotated-cell-5-204">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> </span>
<span id="annotated-cell-5-205">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data_color</span>(</span>
<span id="annotated-cell-5-206">    <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;">"numeric"</span>,</span>
<span id="annotated-cell-5-207">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">palette =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BuPu"</span></span>
<span id="annotated-cell-5-208">  )</span>
<span id="annotated-cell-5-209"></span>
<span id="annotated-cell-5-210">pivot_gt</span>
<span id="annotated-cell-5-211"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</div>
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-5" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="4" data-code-annotation="1">Set the format to <code>dashboard</code> to create a Quarto dashboard.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="5" data-code-annotation="2">Incorporate additional files, like a custom Sass file for themes and a logo.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="12" data-code-annotation="3">Include resources for Posit Connect integration.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="4">4</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="17" data-code-annotation="4">Use Quarto chunk options, as shown in this setup chunk.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="5">5</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="29" data-code-annotation="5">Connect to Posit Connect and retrieve the recently created pin.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="6">6</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="73" data-code-annotation="6">Add value boxes to highlight key text or numbers.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="7">7</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="81,134" data-code-annotation="7">Use the<code>list()</code> format as needed.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="8">8</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="112" data-code-annotation="8">Embed static or interactive plots to enrich your dashboard with text and visuals.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="9">9</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="192" data-code-annotation="9">Include tables as well.</span>
</dd>
</dl>
</section>
<section id="publishing-scripts-and-dashboards" class="level2">
<h2 class="anchored" data-anchor-id="publishing-scripts-and-dashboards">Publishing scripts and dashboards</h2>
<p>There are several ways to publish Quarto dashboards, as detailed in the <a href="https://quarto.org/docs/publishing/">publishing section</a> of the Quarto website. In the webinar, I focused on Posit Connect. If you’re using RStudio, there are multiple deployment options for Connect, including push-button publishing, Git-backed publishing, and command-line publishing. Posit Connect also allows you to schedule document and script refreshes through a user-friendly configuration window.</p>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>Posit’s enterprise publishing platform.↩︎</p></li>
<li id="fn2"><p>To publish scripts, your Connect account must be linked. For details, refer to the <a href="https://docs.posit.co/connect/user/publishing-r/">Publishing documentation</a>. Additionally, you need to provide the environment variables to Connect for use in the script. This can be done via the configuration pane or within the <code>rsconnect::deployApp()</code> command.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/automated-quarto-dashboard/</guid>
  <pubDate>Tue, 13 Aug 2024 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/automated-quarto-dashboard/img/thumbnail.jpeg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Six not-so-basic base R functions</title>
  <link>https://ivelasq.rbind.io/blog/not-so-basic-base-r-functions/</link>
  <description><![CDATA[ 
<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs/loader.js"></script>
<script type="module" id="qwebr-monaco-editor-init">

  // Configure the Monaco Editor's loader
  require.config({
    paths: {
      'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs'
    }
  });
</script>
<script type="module">// Global dictionary to store Monaco Editor instances
const qwebrEditorInstances = {};

// Function that builds and registers a Monaco Editor instance    
globalThis.qwebrCreateMonacoEditorInstance = function (
    initialCode, 
    qwebrCounter) {

  // Retrieve the previously created document elements
  let runButton = document.getElementById(`qwebr-button-run-${qwebrCounter}`);
  let editorDiv = document.getElementById(`qwebr-editor-${qwebrCounter}`);
  
  // Load the Monaco Editor and create an instance
  let editor;
  require(['vs/editor/editor.main'], function () {
    editor = monaco.editor.create(editorDiv, {
      value: initialCode,
      language: 'r',
      theme: 'vs-light',
      automaticLayout: true,           // Works wonderfully with RevealJS
      scrollBeyondLastLine: false,
      minimap: {
        enabled: false
      },
      fontSize: '17.5pt',              // Bootstrap is 1 rem
      renderLineHighlight: "none",     // Disable current line highlighting
      hideCursorInOverviewRuler: true  // Remove cursor indictor in right hand side scroll bar
    });

    // Store the official counter ID to be used in keyboard shortcuts
    editor.__qwebrCounter = qwebrCounter;

    // Store the official div container ID
    editor.__qwebrEditorId = `qwebr-editor-${qwebrCounter}`;

    // Store the initial code value
    editor.__qwebrinitialCode = initialCode;

    // Dynamically modify the height of the editor window if new lines are added.
    let ignoreEvent = false;
    const updateHeight = () => {
      const contentHeight = editor.getContentHeight();
      // We're avoiding a width change
      //editorDiv.style.width = `${width}px`;
      editorDiv.style.height = `${contentHeight}px`;
      try {
        ignoreEvent = true;

        // The key to resizing is this call
        editor.layout();
      } finally {
        ignoreEvent = false;
      }
    };

    // Helper function to check if selected text is empty
    function isEmptyCodeText(selectedCodeText) {
      return (selectedCodeText === null || selectedCodeText === undefined || selectedCodeText === "");
    }

    // Registry of keyboard shortcuts that should be re-added to each editor window
    // when focus changes.
    const addWebRKeyboardShortCutCommands = () => {
      // Add a keydown event listener for Shift+Enter to run all code in cell
      editor.addCommand(monaco.KeyMod.Shift | monaco.KeyCode.Enter, () => {

        // Retrieve all text inside the editor
        qwebrExecuteCode(editor.getValue(), editor.__qwebrCounter);
      });

      // Add a keydown event listener for CMD/Ctrl+Enter to run selected code
      editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {

        // Get the selected text from the editor
        const selectedText = editor.getModel().getValueInRange(editor.getSelection());
        // Check if no code is selected
        if (isEmptyCodeText(selectedText)) {
          // Obtain the current cursor position
          let currentPosition = editor.getPosition();
          // Retrieve the current line content
          let currentLine = editor.getModel().getLineContent(currentPosition.lineNumber);

          // Propose a new position to move the cursor to
          let newPosition = new monaco.Position(currentPosition.lineNumber + 1, 1);

          // Check if the new position is beyond the last line of the editor
          if (newPosition.lineNumber > editor.getModel().getLineCount()) {
            // Add a new line at the end of the editor
            editor.executeEdits("addNewLine", [{
            range: new monaco.Range(newPosition.lineNumber, 1, newPosition.lineNumber, 1),
            text: "\n", 
            forceMoveMarkers: true,
            }]);
          }
          
          // Run the entire line of code.
          qwebrExecuteCode(currentLine, editor.__qwebrCounter,
            EvalTypes.Interactive);

          // Move cursor to new position
          editor.setPosition(newPosition);
        } else {
          // Code to run when Ctrl+Enter is pressed with selected code
          qwebrExecuteCode(selectedText, editor.__qwebrCounter, EvalTypes.Interactive);
        }
      });
    }

    // Register an on focus event handler for when a code cell is selected to update
    // what keyboard shortcut commands should work.
    // This is a workaround to fix a regression that happened with multiple
    // editor windows since Monaco 0.32.0 
    // https://github.com/microsoft/monaco-editor/issues/2947
    editor.onDidFocusEditorText(addWebRKeyboardShortCutCommands);

    // Register an on change event for when new code is added to the editor window
    editor.onDidContentSizeChange(updateHeight);

    // Manually re-update height to account for the content we inserted into the call
    updateHeight();

    // Store the editor instance in the global dictionary
    qwebrEditorInstances[editor.__qwebrCounter] = editor;

  });

  // Add a click event listener to the run button
  runButton.onclick = function () {
    qwebrExecuteCode(editor.getValue(), editor.__qwebrCounter, EvalTypes.Interactive);
  };

}</script>




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/not-so-basic-base-r-functions/thumbnail-wide.jpg" class="img-fluid figure-img" alt="A crop of Leonetto Cappiello, Benedictine, showing a man holding a lantern over a city."></p>
<figcaption>Leonetto Cappiello, Benedictine</figcaption>
</figure>
</div>
<p>R is known for its versatility and extensive collection of packages. As of the publishing of this post, there are over 23 thousand packages on <a href="https://r-universe.dev/search/">R-universe</a>. But what if I told you that you could do some pretty amazing things without loading any packages at all?</p>
<p>There’s a lot of <a href="https://www.rostrum.blog/posts/2023-10-17-nhs-r-2023/">love</a> for base R, and I am excited to pile on. In this blog post, we will explore a few of my favorite “not-so-basic” (i.e., maybe new to you!) base R functions. Click ‘Run code’ in order to see them in action, made possible by <a href="https://docs.r-wasm.org/webr/latest/">webR</a> and the <a href="https://quarto-webr.thecoatlessprofessor.com/">quarto-webr extension</a>!<sup>1</sup></p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>This post includes examples from the <a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/00Index.html">base</a>, <a href="https://stat.ethz.ch/R-manual/R-devel/library/graphics/html/00Index.html">graphics</a>, <a href="https://stat.ethz.ch/R-manual/R-devel/library/datasets/html/00Index.html">datasets</a>, and <a href="https://stat.ethz.ch/R-manual/R-devel/library/stats/html/00Index.html">stats</a> packages, which are automatically loaded when you open R. Additional base R packages include grDevices, utils, and methods.<sup>2</sup></p>
</div>
</div>
<ol type="1">
<li>invisible(): Return an invisible copy of an object</li>
<li>noquote(): Print a character string without quotes</li>
<li>coplot(): Visualize interactions</li>
<li>nzchar(): Find out if elements of a character vector are non-empty strings</li>
<li>with(): Evaluate an expression in a data environment</li>
<li>lengths(): Determine lengths of a list or vector elements</li>
<li>Null coalescing operator <code>%||%</code>: Return first input if not <code>NULL</code>, otherwise return second input</li>
</ol>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>I accidentally had seven functions in my post, even though it’s titled “Six not-so-basic base R functions.” Oops! Consider the null-coalescing operator a bonus, as it’s not part of base R yet. 😊</p>
</div>
</div>
<section id="invisible" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="invisible">1. invisible</h2>
<p>The <code>invisible()</code> function “returns a temporarily invisible copy of an object” by hiding the output of a function in the console. When you wrap a function in <code>invisible()</code>, it will execute normally and can be assigned to a variable or used in other operations, but the result isn’t printed out.</p>

<div class="no-row-height column-margin column-container"><div class="">
<p><strong>Resources</strong></p>
<ul>
<li><a href="https://rdrr.io/github/robertzk/monadicbase/man/invisible.html">invisible documentation</a></li>
<li><a href="https://stackoverflow.com/questions/11653127/what-does-the-function-invisible-do">What does the function invisible() do?</a></li>
<li><a href="https://design.tidyverse.org/out-invisible.html">Tidyverse design guide</a></li>
</ul>
</div></div><p>Below are examples where the functions return their argument <code>x</code>, but one does so invisibly.</p>
<div id="qwebr-insertion-location-1"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-1");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    1
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `f1 <- function(x) x
f1("This prints")`, 
  1);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<div id="qwebr-insertion-location-2"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-2");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    2
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `f2 <- function(x) invisible(x)
f2("This does not print")`, 
  2);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>The way to see invisible output is by saving to a variable or running <code>print()</code>. Both of the below will print:</p>
<div id="qwebr-insertion-location-3"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-3");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    3
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `a <- f2("This prints because it's a saved variable")
a

print(f2("This prints because of print()"))`, 
  3);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>Let’s try another example. Run the chunk below to install the purrr and tidytab packages. Installing the CRAN version of purrr from the webR binary repository is as easy as calling <code>webr::install()</code>. The tidytab package is compiled into a WebAssembly binary on <a href="https://gvelasq.r-universe.dev/tidytab#">R-universe</a> and needs the <code>repos</code> argument to find it. <code>mount = FALSE</code> is due to a bug in the Firefox WebAssembly interpreter. If you’re not using Firefox, then I suggest you try the code below with <code>mount = TRUE</code>! (Note: this might take a few seconds, and longer with <code>mount = FALSE</code>.)</p>
<div id="qwebr-insertion-location-4"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-4");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    4
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `webr::install("purrr")

webr::install("tidytab", 
              mount = FALSE, 
              repos = c("https://gvelasq.r-universe.dev", "https://repo.r-wasm.org"))`, 
  4);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>Using purrr and <code>tidytab::tab2()</code> together results in two <code>NULL</code> list items we do not need.</p>
<div id="qwebr-insertion-location-5"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-5");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    5
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `library(purrr)
library(tidytab)

dat <-
  data.frame(
    col1 = c(3, 2, 2, 1, 2, 1),
    col2 = c(1, 2, 1, 1, 3, 2),
    ct = c(2, 2, 2, 2, 2, 2)
  )

vars <- c("col1", "col2")

tab_run <- function(.x){
  dat |>
    tidytab::tab2(all_of(.x), "ct")
}

purrr::map(.x = vars,
           .f = tab_run)`, 
  5);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>Running <code>invisible()</code> eliminates that!</p>
<div id="qwebr-insertion-location-6"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-6");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    6
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `invisible(purrr::map(.x = vars,
                     .f = tab_run))`, 
  6);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>When writing a function, R can print a lot of stuff implicitly. Using <code>invisible()</code>, you can return results while controlling what is displayed to a user, avoiding cluttering the console with intermediate results.</p>
<p>Per the <a href="https://design.tidyverse.org/out-invisible.html">Tidyverse design guide</a>, “if a function is called primarily for its side-effects, it should invisibly return a useful output.” In fact, many of your favorite functions use <code>invisible()</code>, such as <code>readr::write_csv()</code>, which <a href="https://github.com/tidyverse/readr/blob/e4d640ace3bb6ae095a1114158854a38a1da3a30/R/write.R#L214">invisibly returns</a> the saved data frame.</p>
</section>
<section id="noquote" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="noquote">2. noquote</h2>
<p>The <code>noquote()</code> function “prints character strings without quotes.”</p>

<div class="no-row-height column-margin column-container"><div class="">
<p><strong>Resources</strong></p>
<ul>
<li><a href="https://www.educative.io/answers/what-is-the-noquote-function-in-r">noquote documentation</a></li>
</ul>
</div></div><div id="qwebr-insertion-location-7"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-7");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    7
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `print("Notice the quotation marks?")`, 
  7);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<div id="qwebr-insertion-location-8"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-8");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    8
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `# Implementing the noquote() function 
noquote("Now they're gone, thanks to noquote()!")`, 
  8);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>I use <code>noquote()</code> in a function <code>url_make</code> that converts Markdown reference-style links into HTML links. The input is a character string of a Markdown reference-style link <code>mdUrl</code> and the output is the HTML version of that URL. With <code>noquote()</code>, I can paste the output directly in my text.</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Very proud of my little <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> function to turn a Markdown URL to HTML ☺️ (and save it to your clipboard too). <a href="https://t.co/TsddtTDn9R">pic.twitter.com/TsddtTDn9R</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1519366644782583813?ref_src=twsrc%5Etfw">April 27, 2022</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
<p>Try it out in an anonymous function below!</p>

<div class="no-row-height column-margin column-container"><div class="">
<p>Learn more about this syntax in my <a href="https://ivelasq.rbind.io/blog/understanding-the-r-pipe/">previous blog post</a>!</p>
</div></div><div id="qwebr-insertion-location-9"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-9");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    9
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `"[Isabella's blog](https://ivelasq.rbind.io)" |> (\\(.) {
  text <- sub("\\\\].*", "", sub(".*\\\\[", "", .))
  url <- sub("\\\\).*", "", sub(".*\\\\(", "", .))
  noquote(paste0('Thanks for checking out <a href="', url, '" target = "_blank">', text, '</a>!'))
})()`, 
  9);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
</section>
<section id="coplot" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="coplot">3. coplot</h2>
<p>The <code>coplot()</code> function creates conditioning plots, which are helpful in multivariate analysis. They allow you to explore pairs of variables conditioned on a third so you can understand how relationships change across different conditions.</p>

<div class="no-row-height column-margin column-container"><div class="">
<p><strong>Resources</strong></p>
<ul>
<li><a href="https://stat.ethz.ch/R-manual/R-devel/library/graphics/html/coplot.html">coplot documentation</a></li>
<li><a href="https://intro2r.com/simple-base-r-plots.html#coplots">An introduction to R</a></li>
<li><a href="https://stackoverflow.com/questions/29472360/how-to-read-a-coplot-graph">How to read a coplot() graph</a></li>
</ul>
</div></div><p>The syntax of <code>coplot()</code> is <code>coplot(y ~ x | a, data)</code>, where <code>y</code> and <code>x</code> are the variables you want to plot, <code>a</code> is the conditioning variable, and <code>data</code> is the data frame. The variables provided to <code>coplot()</code> can be either numeric or factors.</p>
<p>Using the built-in <code>quakes</code> dataset, let’s look at the relationship between the latitude (<code>lat</code>) and the longitude (<code>long</code>) and how it varies depending on the depth in km of seismic events (<code>depth</code>).</p>
<div id="qwebr-insertion-location-10"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-10");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    10
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `coplot(lat ~ long | depth, data = quakes)`, 
  10);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>To interpret this plot:</p>
<ul>
<li>Latitude is plotted on the y-axis</li>
<li>Longitude is plotted on the x-axis</li>
<li>The six plots show the relationship of these two variables for different values of depth</li>
<li>The bar plot at the top indicates the range of depth values for each of the plots</li>
<li>The plots in the lower left have the lowest range of depth values and the plots in the top right have the highest range of depth values</li>
</ul>
<p>The orientation of plots might not be the most intuitive. Set <code>rows = 1</code> to make the coplot easier to read.</p>
<div id="qwebr-insertion-location-11"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-11");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    11
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `coplot(lat ~ long | depth, data = quakes,  rows = 1)`, 
  11);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>Here, you can see how the area of Fiji earthquakes grows smaller with increasing depth.</p>
<p>You can also condition on two variables with the syntax <code>coplot(y ~ x| a * b)</code>, where the plots of <code>y</code> versus <code>x</code> are produced conditional on the two variables <code>a</code> and <code>b</code>. Below, the coplot shows the relationship with depth from left to right and the relationship with magnitude (<code>mag</code>) from top to bottom. Check out a more in-depth explanation of this plot on <a href="https://stackoverflow.com/questions/29472360/how-to-read-a-coplot-graph">StackOverflow</a>.</p>
<div id="qwebr-insertion-location-12"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-12");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    12
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `coplot(lat ~ long | depth * mag, data = quakes, number = c(3, 4))`, 
  12);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>I first learned about <code>coplot()</code> thanks to Eric Leung’s tweet. Thanks, Eric!</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
TIL about coplots in base <a href="https://twitter.com/hashtag/RStats?src=hash&amp;ref_src=twsrc%5Etfw">#RStats</a>. in my nearly decade use of R, i've never come across this function to quickly explore pairs of variables conditioned on a third<br><br>library(palmerpenguins)<br>coplot(body_mass_g ~ bill_length_mm|species, data = penguins)<a href="https://t.co/EVpI738VzO">https://t.co/EVpI738VzO</a> <a href="https://t.co/zcTw4HGvnZ">pic.twitter.com/zcTw4HGvnZ</a>
</p>
— Eric Leung 梁挺亮 (<span class="citation" data-cites="erictleung">@erictleung</span>) <a href="https://twitter.com/erictleung/status/1555656643056058369?ref_src=twsrc%5Etfw">August 5, 2022</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
</section>
<section id="nzchar" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="nzchar">4. nzchar</h2>
<p>From the <a href="https://rdrr.io/r/base/nchar.html">documentation</a>, “<code>nzchar()</code> is a fast way to find out if elements of a character vector are non-empty strings”. It returns <code>TRUE</code> for non-empty strings and <code>FALSE</code> for empty strings. This function is particularly helpful when working with environment variables - see an example in the <a href="https://github.com/gojiplus/tuber/blob/4ccf5879b6a3017e88588e65d53ab1e1afce4769/R/delete_channel_sections.R#L21">tuber</a> documentation!</p>

<div class="no-row-height column-margin column-container"><div class="">
<p><strong>Resources</strong></p>
<ul>
<li><a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/nchar.html">nzchar documentation</a></li>
</ul>
</div></div><div id="qwebr-insertion-location-13"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-13");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    13
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `# This is not empty
Sys.getenv("R_LIBS_USER")

# This returns TRUE
nzchar(Sys.getenv("R_LIBS_USER"))`, 
  13);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<div id="qwebr-insertion-location-14"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-14");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    14
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `# This is empty
Sys.getenv("test")

# This returns FALSE
nzchar(Sys.getenv("test"))`, 
  14);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>I have written about nzchar <a href="https://ivelasq.rbind.io/til/asciicast/">in the past</a> and I’ve also explained how to create a GIF using <a href="https://github.com/r-lib/asciicast">asciicast</a>!</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
TIL: nzchar(). Super useful when working with environment variables in R.<br><br>also, <a href="https://twitter.com/hashtag/asciicast?src=hash&amp;ref_src=twsrc%5Etfw">#asciicast</a> is amazing! install the GIF converter with remotes::install_github('r-lib/asciicast', ref = remotes::github_pull(24)) <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> h/t <a href="https://twitter.com/GaborCsardi?ref_src=twsrc%5Etfw"><span class="citation" data-cites="GaborCsardi">@GaborCsardi</span></a> <a href="https://t.co/pCZQLCNaDl">pic.twitter.com/pCZQLCNaDl</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1524193394037342211?ref_src=twsrc%5Etfw">May 11, 2022</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
</section>
<section id="with" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="with">5. with</h2>
<p>If you use base R, you’ve likely encountered the dollar sign <code>$</code> when evaluating expressions with variables from a data frame. The <code>with()</code> function lets you reference columns directly, eliminating the need to repeat the data frame name multiple times. This makes your code more concise and easier to read.</p>

<div class="no-row-height column-margin column-container"><div class="">
<p><strong>Resources</strong></p>
<ul>
<li><a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/with.html">with documentation</a></li>
<li><a href="https://stackoverflow.com/questions/42283479/when-to-use-with-function-and-why-is-it-good">When to use ‘with’ function and why is it good?</a></li>
</ul>
</div></div><p>So, instead of writing <code>plot(mtcars$hp, mtcars$mpg)</code>, you can write:</p>
<div id="qwebr-insertion-location-15"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-15");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    15
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `with(mtcars, plot(hp, mpg))`, 
  15);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>This is particularly handy to use with the base R pipe <code>|&gt;</code>:</p>
<div id="qwebr-insertion-location-16"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-16");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    16
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `mtcars |> with(plot(hp, mpg))`, 
  16);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p><a href="https://twitter.com/mikelove/status/1197190835994943489">Michael Love’s Tweet</a> shows how to connect a dplyr chain to a base plot function using <code>with()</code>:</p>
<div id="qwebr-insertion-location-17"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-17");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    17
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `webr::install("dplyr")
library(dplyr)
        
mtcars |> dplyr::filter(hp > 100) |> with(plot(hp, mpg))`, 
  17);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
</section>
<section id="lengths" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="lengths">6. lengths</h2>
<p><code>lengths()</code> is a more efficient version of <code>sapply(df, length)</code>. <code>length()</code> determines the number of elements in an object, and <code>lengths()</code> will provide the lengths of elements across columns in the data frame.</p>

<div class="no-row-height column-margin column-container"><div class="">
<p><strong>Resources</strong></p>
<ul>
<li><a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/lengths.html">lengths documentation</a></li>
<li><a href="https://stackoverflow.com/questions/71969291/summing-the-lengths-of-lists-inside-a-list-in-r">Summing the lengths of lists inside a list in R</a></li>
</ul>
</div></div><div id="qwebr-insertion-location-18"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-18");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    18
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `df <- data.frame(A = c(1, 2, 3), B = c(4, 5, 6), C = c(7, 8, 9))

lengths(df)`, 
  18);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>Pretty straightforward but I think it is a neat function :)</p>
<p><strong>Note 2024-01-21</strong>: As <a href="https://twitter.com/ProfBootyPhD"><span class="citation" data-cites="ProfBootyPhD">@ProfBootyPhD</span></a> <a href="https://twitter.com/ProfBootyPhD/status/1748025353648689557">mentioned on Twitter</a>, a better example of <code>lengths()</code> would be a list “since all the columns of a df are required to be the same length.” Here is the example from StackOverflow:</p>
<div id="qwebr-insertion-location-19"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-19");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    19
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `df1 <- data.frame(x = 1:5, y = letters[1:5])
df2 <- data.frame(x = 1:15, y = letters[1:15])
df3 <- data.frame(x = 1:25, y = letters[1:25])
df4 <- data.frame(x = 1:6, y = letters[1:6])
df5 <- data.frame(x = 1:8, y = letters[1:8])

l1 <- list(df1, df2)
l2 <- list(df3, df4, df5)
mylist <- list(l1, l2)

lengths(mylist)`, 
  19);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
</section>
<section id="null-coalescing-operator-in-r" class="level2">
<h2 class="anchored" data-anchor-id="null-coalescing-operator-in-r">7. Null-coalescing operator in R, %||%</h2>
<p>OK, this one isn’t in base R – yet! In the <a href="https://developer.r-project.org/blosxom.cgi/R-devel/2023/10/26#n2023-10-26">upcoming release</a>, R will automatically provide the <a href="https://en.m.wikipedia.org/wiki/Null_coalescing_operator">null-coalescing operator</a>, <code>%||%</code>. Per the release notes:</p>
<blockquote class="blockquote">
<p>‘L %||% R’ newly in base is an expressive idiom for the ‘if(!is.null(L)) L else R’ or ‘if(is.null(L)) R else L’ phrases.</p>
</blockquote>
<p>Or, in code:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">%||%</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, y) {</span>
<span id="cb1-2">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is_null</span>(x)) y <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> x</span>
<span id="cb1-3">}</span></code></pre></div></div>
<p>Essentially, this means: if the first (left-hand) input <code>x</code> is <code>NULL</code>, return <code>y</code>. If <code>x</code> is not <code>NULL</code>, return the input.</p>
<p>It was great to see Jenny Bryan and the R community celebrate the formal inclusion of the null-coalescing operator into the R language on <a href="https://fosstodon.org/@jennybryan/111302964025298493">Mastodon</a>. The null-coalescing operator is particularly useful for R package developers, as highlighted by Jenny in her <a href="https://www.youtube.com/watch?v=7oyiPBjLAWY">useR! 2018 keynote</a>, used when the tidyverse team needs to assess whether an argument has been supplied, or if the default value which is commonly <code>NULL</code> has been passed, meaning that the default argument has been supplied.</p>
<img src="https://ivelasq.rbind.io/blog/not-so-basic-base-r-functions/example.png" class="img-fluid" alt="Jenny Bryan's Code smell and feels talk, showing the slide showing an example of the use of the null-coalescing operator.">
<center>

<a href="https://speakerdeck.com/jennybc/code-smells-and-feels?slide=69" target="_blank">Jenny Bryan’s Code smell and feels null-coalescing operator example</a>

</center>
<p><br> However, the null-coalescing operator can also be useful in interactive use, for functions that take <code>NULL</code> as a valid argument. In this case, if supplied in the argument itself it can yield different interesting behaviors. For example:</p>
<div id="qwebr-insertion-location-20"></div>
<script type="module">
// Retrieve the insertion point
const currentDocumentLocation = document.getElementById("qwebr-insertion-location-20");

// Initalize an interactive element
const initializedElement =   qwebrCreateInteractiveElement(
    20
  );

// Add the interactive element into the document scope
currentDocumentLocation.appendChild(initializedElement);

// Initialize a Monaco Editor Instance
qwebrCreateMonacoEditorInstance(
  `# rlang must be loaded because the operator is not available in base R yet
webr::install("rlang")
library(rlang)

add_commas <- function(x) {
  if (length(x) <= 1) {
    collapse_arg <- NULL
  } else {
    collapse_arg <- ", "
  }
  print(paste0(x, collapse = collapse_arg %||% ""))
}

add_commas(c("apples"))
add_commas(c("apples", "bananas"))`, 
  20);
</script>
<noscript>Please enable JavaScript to experience the dynamic code cell content on this page.</noscript>
<p>There’s more <a href="https://fosstodon.org/@eddelbuettel@mastodon.social/111295691967509884">discussion</a> about the utility of the function.</p>
</section>
<section id="the-fun-ctions-never-stop" class="level2">
<h2 class="anchored" data-anchor-id="the-fun-ctions-never-stop">The fun-ctions never stop</h2>
<p>Want even more functions (base R or not)? Here are some other resources to check out:</p>
<ul>
<li><a href="https://masalmon.eu/tags/useful-functions/">Maëlle Salmon’s blog posts on useful functions</a></li>
<li><a href="https://www.neilwright.uk/posts/five-r-functions">Neil Wright’s post on five useful R functions</a></li>
<li><a href="https://yihui.org/en/2023/10/three-functions/">Yihui Xie’s list of three useful functions in base R</a></li>
<li><a href="https://adventofcode.ellakaye.co.uk/2023/day/1/">Ella Kaye’s Advent of Code walkthroughs</a></li>
<li><a href="https://twitter.com/moh_fodil/status/1537078271501905920">Ihaddaden M. EL Fodil, Ph.D’s Twitter thread</a></li>
<li>TidyX Screencasts, such as <a href="https://www.youtube.com/watch?v=bh-2JONnJ0k">this one</a></li>
</ul>
<p>Thanks to all community members sharing their code and functions!</p>
<p><em>Liked this article? I’d love for you to share!</em></p>
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs"><li class="nav-item"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" aria-controls="tabset-1-1" aria-selected="true" href="">Twitter</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" aria-controls="tabset-1-2" aria-selected="false" href="">Mastodon</a></li></ul>
<div class="tab-content">
<div id="tabset-1-1" class="tab-pane active" aria-labelledby="tabset-1-1-tab">
<p></p><div id="tweet-66622"></div><script>tweet=<!DOCTYPE html>
<html lang="en" class="dog">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>X / ?</title>
    <meta name="version" content="1">
    <link href="https://abs.twimg.com/favicons/twitter.3.ico" rel="shortcut icon" type="image/x-icon">
    <link rel="stylesheet" href="https://abs.twimg.com/errors/fullscreen_errors-047ca1475a6efac7c9c89a9ff92b7a20.css">
  </head>
  <body dir="auto">
    <div class="top">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1519 200">
        <defs/>
        <path d="M708 103l9-5 13 1 2-2 5 1h8l1-1 42-5h7l7 3v1l12-2a9368 9368 0 0129-6l2-5 12 1 6-2 3 1 2 1v-2l13-2v1l4 2 7-1h1l17-3 1 2 4-1 18-7 3-1 4-1h9l13-1 1-4 3-2 13 1v2l22-2 10-3h6l10 5 16-5 15-3 2-1 8-4 6-2 12-1 7-2 8 5 7 1 22-9h7l5-1v-1l25-3 1 2 5 2v1h11l2 1 8-4h3l-1 1h11l10-6 6 3 9-1 4-1 1 1 1-2 6-1 1-1 10-2h2l7-5v1h4l3-1c11 0 23 2 34-3 2-2 7 0 10 0l12 1 4 1 9 2 12-1 11-3 11 1h4l10-6 17 1 2 1c9 2 19-3 22-11l1-1 9 1 15-5c3-1 9 4 9-5 5 0 5 3 5 7l2 3 4-1 4-2 9-4 3-3h3l8-4 6-3 26 2 7-4h18l7 1c10 3 13-6 17-12l8 4 3-1 14-3 15-2a38 38 0 01-5-1l-8-4 7-8 8-4-10-136-922 71 16 205z"/>
        <path d="M-36 193l9-5 13 1 2-2 5 1h8l1-1 42-5h7l7 3v1l12-2a9328 9328 0 0129-6l2-5 12 1 6-2 3 1 2 1v-2l13-2v1l4 2 7-1h1l17-3 1 2 4-1 18-7 3-1 4-1h9l13-1 1-4 3-2 13 1v2l22-2 10-3h6l10 5 16-5 15-3 2-1 8-4 6-2 12-1 7-2 8 5 7 1 22-9h7l5-1v-1l25-3 1 2 5 2v1h11l2 1 8-4h3l-1 1h9a6 6 0 002 0l10-6 6 3 9-1 4-1a6 6 0 001 1l1-2 6-1 1-1 10-2h2l7-5v1h4l3-1c11 0 23 2 34-3 2-2 7 0 10 0l12 1 4 1 9 2 12-1 11-3 11 1h4l10-6 17 1 2 1c9 2 19-3 22-11l1-1 9 1 15-5c3-1 9 4 9-5 5 0 5 3 5 7l2 3 4-1 4-2 9-4 3-3h3l8-4 6-3 26 2 7-4h18l7 1c10 3 13-6 17-12l8 4 3-1 14-3 15-2a37 37 0 01-5-1l-8-4 7-8 8-4-10-136-922 71 16 205z"/>
      </svg>
    </div>
    <div class="container">
      <div class="content">
        <a href="https://twitter.com" title="X logo">
          <svg viewBox="0 0 24 24" aria-hidden="true" class="x-logo"><g><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path></g></svg>
        </a>
        <h1 id="header">Nothing to see here</h1>
        <p id="description">Looks like this page doesn’t exist. Here’s a picture of a poodle sitting in a chair for your trouble.</p>

          <a id="button_search" href="/" class="button">Looking for this?</a>

      </div>
      <img id="image" src="https://abs.twimg.com/errors/ErrorState_NotFound.png" alt="A primped poodle with a bow in its hair sitting in a chair like a human.">
      <div class="footer">
        <ul>
          <li><a href="https://twitter.com/" id="footer_home">Home</a></li>
          <li><a href="https://status.twitterstat.us/" id="footer_status">Status</a></li>
          <li><a href="https://twitter.com/tos" id="footer_tos">Terms of Service</a></li>
          <li><a href="https://twitter.com/privacy" id="footer_privacy">Privacy Policy</a></li>
          <li><a href="https://support.twitter.com/articles/20170514" id="footer_cookie">Cookie Policy</a></li>
          <li><a href="https://legal.twitter.com/imprint" id="footer_imprint">Imprint</a></li>
          <li><a href="https://business.twitter.com/en/help/troubleshooting/how-twitter-ads-work.html" id="footer_ads">Ads info</a></li>
          <li dir="ltr">&copy; X Corp. <span id="copyright-year">&emsp;&emsp;&emsp;&emsp;</span></li>
        </ul>
      </div>
    </div>
  </body>
  <script src="https://abs.twimg.com/errors/404-8651f633fd193e0b546010676a4fac06.js"></script>

;document.getElementById("tweet-66622").innerHTML = tweet["html"];<p></p>
</div>
<div id="tabset-1-2" class="tab-pane" aria-labelledby="tabset-1-2-tab">
<iframe src="https://fosstodon.org/@ivelasq3/111772069621750384/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen">
</iframe>
<script src="https://fosstodon.org/embed.js" async="async"></script>
</div>
</div>
</div>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>Many thanks to the following resources for making this post possible:</p>
<ul>
<li>George Stagg’s webR and the <a href="https://docs.r-wasm.org/webr/latest/">webR documentation</a>.</li>
<li>James Joseph Balamuta’s <a href="https://quarto-webr.thecoatlessprofessor.com/">Quarto extension for webR</a>.</li>
<li>Brian Kent’s <a href="https://blog.theapricot.io/posts/quarto-headers/">blog post</a> on adding headers to a Quarto blog on Netlify.</li>
</ul>
↩︎</li>
<li id="fn2"><p>This is a <a href="https://rpubs.com/Mentors_Ubiqum/list_packages">handy guide</a> for seeing the packages loaded in your R session!↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>reference</category>
  <guid>https://ivelasq.rbind.io/blog/not-so-basic-base-r-functions/</guid>
  <pubDate>Wed, 17 Jan 2024 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/not-so-basic-base-r-functions/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Using flexdashboard to create a GitHub Actions-powered YouTube feed</title>
  <link>https://ivelasq.rbind.io/blog/automated-youtube-dashboard/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/automated-youtube-dashboard/img/thumbnail-wide.jpg" class="img-fluid figure-img" alt="A group of people around a camera in a bright, colorful room"></p>
<figcaption>Utagawa Yoshikazu, Early Foreign Photographer in Yokohama</figcaption>
</figure>
</div>
<p><a href="https://rladies.org">R-Ladies</a> organizes a multitude of inspiring and exciting <a href="https://www.meetup.com/pro/rladies">Meetups</a> worldwide. However, due to work, time zones, or other commitments, I can’t attend them all. Fortunately, since the pandemic began, many Meetup hosts have started to record webinars and post them online. This provides a great opportunity to catch up on things I’ve missed afterward.</p>
<p>In addition to the Meetups, R-Ladies also maintains a variety of YouTube channels. The primary channel, <a href="https://www.youtube.com/channel/UCDgj5-mFohWZ5irWSFMFcng">R-Ladies Global</a>, offers the largest collection of videos. Local chapters often have their individual accounts as well. To simplify the process of accessing videos from multiple chapters, I wanted a convenient tool for viewing an aggregated list of videos. I also thought it would be helpful to have the ability to search videos based on presenters, topics, and other criteria.</p>
<p>So, I set out to build a dashboard with <a href="https://pkgs.rstudio.com/flexdashboard">{flexdashboard}</a> that would display all this information. {flexdashboard} is built on <a href="https://rmarkdown.rstudio.com">R Markdown</a>, which allowed me to use R to personalize a dashboard with custom colors and styles. And, of course, I used R to pull in the data. <a href="https://github.com/soodoku/tuber/#sweet_potato-tuber-access-youtube-api-via-r">{tuber}</a> provides access to the <a href="https://developers.google.com/youtube/v3/getting-started">YouTube Data API v3</a> with R, a straightforward tool for getting the data I needed.</p>
<p>There were challenges along the way. Since Meetups happen fairly often, I hoped to use <a href="https://github.com/features/actions">GitHub Actions</a> to automatically refresh the dashboard every 24 hours. Unfortunately, I encountered difficulties due to the authentication options provided by {tuber}, which supports YouTube’s <a href="https://developers.google.com/youtube/v3/guides/authentication">OAuth 2.0</a> authorization process. I reached out to my <a href="https://github.com/gvelasq">brother</a> for help since we’d previously collaborated on an <a href="https://github.com/ivelasq/wizehiver">API wrapper</a> in R. The project <a href="https://github.com/ivelasq/rladies-video-feed/graphs/contributors">stalled</a> as we tried unsuccessfully to get YouTube’s OAuth 2.0 flow to work with GitHub Actions.</p>
<p>We had a breakthrough when we realized that videos could be accessed relatively painlessly by skipping OAuth 2.0 and using an <a href="https://cloud.google.com/api-keys/docs/overview">API key</a> instead. After two <a href="https://github.com/soodoku/tuber/pulls?q=is%3Apr+author%3Agvelasq">pull requests</a> to add API key authentication to {tuber}, we are delighted to announce that the GitHub version of {tuber} now contains functions that work well with GitHub Actions. You can find the finished (and automated!) dashboard here:</p>
<center>
<a href="https://ivelasq.github.io/rladies-video-feed"><img src="https://ivelasq.rbind.io/blog/automated-youtube-dashboard/img/dashboard-gif.gif" style="width:70%"></a><br>

<a href="https://ivelasq.github.io/rladies-video-feed" class="uri">https://ivelasq.github.io/rladies-video-feed</a>

</center>
<p><br></p>
<p>The <a href="https://github.com/ivelasq/rladies-video-feed">code</a> for the dashboard is on GitHub in case you want to reuse it for another set of channels!</p>
<div class="callout callout-style-default callout-warning callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Warning</span>YouTube RSS vs.&nbsp;YouTube API
</div>
</div>
<div class="callout-body-container callout-body">
<p>I originally used the <a href="https://robertmyles.github.io/tidyRSS">tidyRSS</a> package to pull the list of videos from YouTube. However, the YouTube RSS feed limits results to the latest 15 videos. The code is still available in the repo if you would like to take a look. This is a good option if you only want the most recent stream of content and would like to avoid setting up any Google credentials. Thanks to the <a href="http://r4ds.io/join">R4DS channel</a> and <a href="https://twitter.com/thomas_mock">Tom Mock</a> for pointing me in the right direction!</p>
</div>
</div>
<p>The rest of the post describes how we built the dashboard. We learned quite a bit in the process!</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/automated-youtube-dashboard/img/meme2.jpg" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<section id="get-a-youtube-api-key" class="level2">
<h2 class="anchored" data-anchor-id="get-a-youtube-api-key">Get a YouTube API key</h2>
<p>As is often the case with anything to do with Google, first, you must get credentials. In this example, we were interested in an API key that would work with the YouTube Data API v3.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/automated-youtube-dashboard/img/meme1.jpg" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<ol type="1">
<li>Log into the <a href="https://console.cloud.google.com">Google Cloud Platform Console</a>.</li>
<li>Create a <a href="https://console.cloud.google.com/projectcreate">new project</a>.</li>
<li>From your dashboard, click to ‘Go to APIs Overview’ and navigate to ‘<a href="https://console.cloud.google.com/apis/credentials">Credentials</a>’ in the sidebar.</li>
<li>At the top, click ‘Create Credentials’ and choose ‘API key’.</li>
<li>Your API key will pop up. Save it for reference later in this walkthrough.</li>
<li>In the pop-up window (or in the hamburger menu for the API key), click ‘Edit API key’.</li>
<li>Scroll to the bottom and under ‘API restrictions’, select ‘Restrict key’, select ‘YouTube Data API v3’ from the dropdown menu, click ‘OK’ to exit the dropdown menu, then click ‘Save’. This will restrict your API key so that it can only be used with the YouTube Data API v3, which will limit its usefulness should anyone get ahold of your key.</li>
</ol>
</section>
<section id="store-your-youtube-api-key" class="level2">
<h2 class="anchored" data-anchor-id="store-your-youtube-api-key">Store your YouTube API key</h2>
<p>Now that you have an API key, you will want to save it in your R environment (<code>.Renviron</code>) using <a href="https://usethis.r-lib.org/reference/edit.html"><code>usethis::edit_r_environ()</code></a> if working interactively or in your <a href="https://docs.github.com/en/actions/security-guides/encrypted-secrets">repository secrets</a> if using GitHub Actions. Storing the API key as an environment variable allows you to access it easily without the need to manually input it every time you run your code. GitHub Actions can interact with the API without manual intervention, and storing it as a repository secret keeps the key separate from your source code so it is not exposed to others.</p>
<p>To do this, follow the instructions below:</p>
<ol type="1">
<li>Install the CRAN version of <a href="https://httr2.r-lib.org">{httr2}</a> and the GitHub version of <a href="https://github.com/soodoku/tuber/blob/master/NEWS.md">{tuber}</a>. <a href="https://pak.r-lib.org">{pak}</a> allows for easy installation of packages, whether they are on CRAN, GitHub, pull requests, etc.</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("pak")      # Install {pak} if not yet installed</span></span>
<span id="cb1-2">pak<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pak</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"httr2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"soodoku/tuber"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># CRAN and GitHub syntax side by side!</span></span></code></pre></div></div>
<ol start="2" type="1">
<li>On your local machine, save your YouTube API key in <code>.Renviron</code>. Running the code below will prompt you to save the API key. Paste your API key into the pop-up window:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">tuber<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">yt_set_key</span>()</span></code></pre></div></div>
<p>Now your YouTube API key is saved as <code>YOUTUBE_KEY</code> in <code>.Renviron</code>!</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>API key security
</div>
</div>
<div class="callout-body-container callout-body">
<p>Using an API key is considered <a href="https://httr2.r-lib.org/articles/wrapping-apis.html#security-considerations">relatively insecure</a> since the key itself will be included in queries sent over the Internet and thus could be intercepted. If you are considering including an API key in a package or in public source code, we recommend using the <a href="https://httr2.r-lib.org/articles/wrapping-apis.html#secret-management">secret management</a> functions provided by {httr2}.</p>
<p>If you would like to encrypt your API key, you can do so using {httr2} and a few arguments we built into {tuber}. You can first create a {tuber} package key stored as <code>TUBER_KEY</code> with <code>tuber::yt_set_key(httr2::secret_make_key(), type = "package")</code> and an encrypted <code>YOUTUBE_KEY</code> with <code>tuber::yt_set_key(httr2::secret_encrypt("YOUR_UNENCRYPTED_API_KEY", key = "TUBER_KEY"))</code>. To retrieve a decrypted <code>YOUTUBE_KEY</code> in your code, you can then run <code>tuber::yt_get_key(decrypt = TRUE)</code>.</p>
<p>Please note that encrypting your API key will keep it safe if others don’t have your <code>TUBER_KEY</code> to decrypt it, but it will still need to be included unencrypted in queries to interact with the YouTube Data API.</p>
</div>
</div>
</section>
<section id="pull-and-clean-data" class="level2">
<h2 class="anchored" data-anchor-id="pull-and-clean-data">Pull and clean data</h2>
<p>Woohoo, you are credentialed! It’s time for the fun part — pulling and cleaning data. I did this in a script called <a href="https://github.com/ivelasq/rladies-video-feed/blob/main/data-processing.R"><code>data_processing.R</code></a>.</p>
<p>In addition to {tuber}, here are other packages that will aid you in the cleaning process:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" 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>(tuber) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># GitHub version, installed with pak::pak(soodoku/tuber)</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(readr)</span>
<span id="cb3-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb3-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(stringr)</span>
<span id="cb3-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DT)</span></code></pre></div></div>
<p>Create a spreadsheet with the channels you are interested in. I created this manually — I just searched on YouTube for all the R-Ladies channels I could find. To make this workflow as programmatic as possible, I only included the chapter name, thumbnail, and channel ID.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb4-2">  <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;">"https://github.com/ivelasq/rladies-video-feed/blob/main/r-ladies_channels.csv"</span>)</span>
<span id="cb4-3">  </span>
<span id="cb4-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(dat)</span></code></pre></div></div>
<pre><code>  chapter            image                                              id   
  &lt;chr&gt;              &lt;chr&gt;                                              &lt;chr&gt;
1 R-Ladies Global    https://yt3.ggpht.com/ytc/AKedOLRM4FPiPcPBdFUmYWR… UCDg…
2 R-Ladies Baltimore https://yt3.ggpht.com/RQifC3qp_7AFeTc48-QV1i4WBNM… UC9U…
3 R-Ladies Philly    https://yt3.ggpht.com/ytc/AKedOLShIKBvPUKqbvm_Cpu… UCPq…
4 R-Ladies STL       https://yt3.ggpht.com/ytc/AKedOLSBA7rlz1yvbIJ7TVN… UCQ7…
5 R-Ladies Sydney    https://yt3.ggpht.com/ytc/AKedOLQnaU-dJbb14j2RE6W… UCkr…
6 R-Ladies Vancouver https://yt3.ggpht.com/3yf0Zo8-VKffrG-dRT_Gs85xX_x… UCX5…</code></pre>
<div class="callout callout-style-default callout-warning callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Warning</span>YouTube Channel IDs
</div>
</div>
<div class="callout-body-container callout-body">
<p>Some YouTube channels have ‘custom IDs’ like RLadiesGlobal. These won’t work in {tuber}; you need the original IDs. The best way I found to get this ID is to click on a video from a channel. Then, scroll down to the description and click the channel name from that video. The original ID will appear in the URL after <code>/channel/</code>. A good idea for a future Shiny app would be a way to pull this information from the YouTube API…</p>
</div>
</div>
<p>Now, create a few more columns with <code>dplyr::mutate()</code> that expand the URLs into HTML format:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">dat_urls <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb6-2">  dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-3">  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;">mutate</span>(</span>
<span id="cb6-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">feed =</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;">"https://www.youtube.com/feeds/videos.xml?channel_id="</span>, id),</span>
<span id="cb6-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">feed_url =</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;">"yt:channel:"</span>, id),</span>
<span id="cb6-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">channel_image_url =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(</span>
<span id="cb6-7">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;img src='"</span>,</span>
<span id="cb6-8">      image,</span>
<span id="cb6-9">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"' alt='Hex Sticker for Chapter' width='40'&gt;&lt;/img&gt;"</span>,</span>
<span id="cb6-10">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" &lt;a href='https://www.youtube.com/channel/"</span>,</span>
<span id="cb6-11">      id,</span>
<span id="cb6-12">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"' target='_blank'&gt;"</span>,</span>
<span id="cb6-13">      chapter,</span>
<span id="cb6-14">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;/a&gt;&lt;br&gt;"</span></span>
<span id="cb6-15">    ),</span>
<span id="cb6-16">  )</span></code></pre></div></div>
<p>The {tuber} <a href="https://soodoku.github.io/tuber/reference/index.html">documentation</a> describes the many functions available to you. Many of these require OAuth 2.0 authentication. Since I had only the channel IDs, I wanted to use <code>list_channel_videos()</code> to get a complete list of videos from the channels, which thankfully works with an API key!</p>
<p>For example, for the R-Ladies Global channel, you could run <code>list_channel_videos()</code> to get its (currently 165) videos:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">tuber<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list_channel_videos</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"UCDgj5-mFohWZ5irWSFMFcng"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max_results =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">auth =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"key"</span>)</span></code></pre></div></div>
<p>What if you want the results for all the channels we have in our spreadsheet? I used a loop for this.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="annotated-cell-8" style="background: #f1f3f5;"><pre class="sourceCode r code-annotation-code code-with-copy code-annotated"><code class="sourceCode r"><a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-8-1" class="code-annotation-target">dat_videos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span></span>
<span id="annotated-cell-8-2"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-8-3" class="code-annotation-target"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(dat_urls)) {</span>
<span id="annotated-cell-8-4">  tmp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-8-5" class="code-annotation-target">    dat_urls[i, ][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="4" onclick="event.preventDefault();">4</a><span id="annotated-cell-8-6" class="code-annotation-target">    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;">pull</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="5" onclick="event.preventDefault();">5</a><span id="annotated-cell-8-7" class="code-annotation-target">    tuber<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list_channel_videos</span>(</span>
<span id="annotated-cell-8-8">      .,</span>
<span id="annotated-cell-8-9">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">part =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"snippet"</span>,</span>
<span id="annotated-cell-8-10">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">config =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"maxResults"</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;">200</span>),</span>
<span id="annotated-cell-8-11">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">auth =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"key"</span></span>
<span id="annotated-cell-8-12">    )</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="6" onclick="event.preventDefault();">6</a><span id="annotated-cell-8-13" class="code-annotation-target">  dat_videos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> 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;">bind_rows</span>(dat_videos, tmp)</span>
<span id="annotated-cell-8-14">}</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-8" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="1" data-code-annotation="1">Starting with an empty data frame called <code>dat_videos</code>,</span>
</dd>
<dt data-target-cell="annotated-cell-8" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="3" data-code-annotation="2">For each row in <code>dat_urls</code> (which contains the channel IDs),</span>
</dd>
<dt data-target-cell="annotated-cell-8" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="5" data-code-annotation="3">Find the channel ID,</span>
</dd>
<dt data-target-cell="annotated-cell-8" data-target-annotation="4">4</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="6" data-code-annotation="4">Pull the ID,</span>
</dd>
<dt data-target-cell="annotated-cell-8" data-target-annotation="5">5</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="7" data-code-annotation="5">Run it through <code>list_channel_videos()</code>, and</span>
</dd>
<dt data-target-cell="annotated-cell-8" data-target-annotation="6">6</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="13" data-code-annotation="6">Add the information as rows to <code>dat_videos</code>.</span>
</dd>
</dl>
<p>The arguments in <code>list_channel_videos()</code> gave me all the columns I am interested in with <code>part = "snippet"</code>. Notice that there’s a default limit for the number of videos pulled from the API. I bumped that up a bit with the <code>maxResults</code> argument.</p>
<p>Then, I brought back the URL info:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">dat_join <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb8-2">  dat_videos <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb8-3">  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;">left_join</span>(., dat_urls, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">join_by</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"snippet.channelId"</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;">"id"</span>))</span></code></pre></div></div>
<p>This results in a <strong>lot</strong> of information for each video. I cleaned it up a bit so that the data frame contained only the relevant columns in HTML format.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">dat_dashboard <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb9-2">  dat_join <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb9-3">  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;">mutate</span>(</span>
<span id="cb9-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">video_url =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(</span>
<span id="cb9-5">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;a href='https://www.youtube.com/watch?v="</span>,</span>
<span id="cb9-6">      snippet.resourceId.videoId,</span>
<span id="cb9-7">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"' target='_blank'&gt;"</span>,</span>
<span id="cb9-8">      snippet.title,</span>
<span id="cb9-9">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;/a&gt;"</span></span>
<span id="cb9-10">    ),</span>
<span id="cb9-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">channel_url =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(</span>
<span id="cb9-12">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;img src='"</span>,</span>
<span id="cb9-13">      image,</span>
<span id="cb9-14">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"' alt='Hex Sticker for Chapter' width='40'&gt;&lt;/img&gt;"</span>,</span>
<span id="cb9-15">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;a href='https://www.youtube.com/channel/"</span>,</span>
<span id="cb9-16">      snippet.channelId,</span>
<span id="cb9-17">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"' target='_blank'&gt;"</span>,</span>
<span id="cb9-18">      chapter,</span>
<span id="cb9-19">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;/a&gt;"</span></span>
<span id="cb9-20">    ),</span>
<span id="cb9-21">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">date =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_sub</span>(snippet.publishedAt, <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;">10</span>))</span>
<span id="cb9-22">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb9-23">  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;">arrange</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">desc</span>(snippet.publishedAt)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb9-24">  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>(date, chapter, channel_url, video_url, channel_image_url)</span></code></pre></div></div>
<p>See the <a href="https://github.com/ivelasq/rladies-video-feed/blob/main/data-processing.R">final data processing file on GitHub</a>.</p>
</section>
<section id="create-a-flexdashboard" class="level2">
<h2 class="anchored" data-anchor-id="create-a-flexdashboard">Create a flexdashboard</h2>
<p>You have the YouTube data — time to create a pretty dashboard!</p>
<p>My flexdashboard started as R Markdown files often do: with a YAML header. I specified an orientation (columns) and added the link to the GitHub repository in the navigation bar.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb10-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb10-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;">"R-Ladies YouTube Video Feed"</span></span>
<span id="cb10-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">output</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>
<span id="cb10-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  flexdashboard:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:flex_dashboard</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb10-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;">orientation</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;"> columns</span></span>
<span id="cb10-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;">navbar</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb10-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">{</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">icon</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;">"fa-github"</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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">href</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;">"https://github.com/ivelasq/rladies-video-feed"</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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">align</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;"> right </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">}</span></span>
<span id="cb10-8"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
<section id="add-customization" class="level3">
<h3 class="anchored" data-anchor-id="add-customization">Add customization</h3>
<p>If you’d like your dashboard to have a custom look, the <a href="https://rstudio.github.io/bslib">{bslib}</a> package is a great option. It can add different colors and fonts directly in the YAML header. Make sure to add <code>library(bslib)</code> in the actual code part of your <code>.Rmd</code> file. I used the R-Ladies style guide to fill out the rest of the YAML header:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb11-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb11-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;">"R-Ladies YouTube Video Feed"</span></span>
<span id="cb11-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">output</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>
<span id="cb11-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  flexdashboard:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:flex_dashboard</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb11-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;">orientation</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;"> columns</span></span>
<span id="cb11-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;">navbar</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb11-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">{</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">icon</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;">"fa-github"</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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">href</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;">"https://github.com/ivelasq/rladies-video-feed"</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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">align</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;"> right </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">}</span></span>
<span id="cb11-8"><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;">theme</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb11-9"><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;">version</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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb11-10"><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;">bg</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;">"#FDF7F7"</span></span>
<span id="cb11-11"><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;">fg</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;">"#88398A"</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> # purple</span></span>
<span id="cb11-12"><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;">primary</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;">"#88398A"</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> # purple</span></span>
<span id="cb11-13"><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;">base_font</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb11-14"><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;">google</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;">"Lato"</span></span>
<span id="cb11-15"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
</section>
<section id="add-packages-for-the-dashboard" class="level3">
<h3 class="anchored" data-anchor-id="add-packages-for-the-dashboard">Add packages for the dashboard</h3>
<p>Below the YAML header, add the packages you need. I used <code>source()</code> to read the <code>data-processing.R</code> script.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(flexdashboard)</span>
<span id="cb12-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(bslib)</span>
<span id="cb12-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">source</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data-processing.R"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">local =</span> knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">knit_global</span>())</span></code></pre></div></div>
</section>
</section>
<section id="design-the-flexdashboard-layout" class="level2">
<h2 class="anchored" data-anchor-id="design-the-flexdashboard-layout">Design the flexdashboard layout</h2>
<p>This dashboard has a simple layout: just a sidebar and the main section. I recommend checking out the flexdashboard documentation to see all the <a href="https://pkgs.rstudio.com/flexdashboard/articles/layouts.html">layout options</a> available to you.</p>
<p>This code builds out the sidebar section. I created a list of each R-Ladies chapter that I was able to find and arranged them by name. With <code>htmltools::HTML()</code>, the dashboard can render the URLs as HTML (the reason for all that manipulation earlier on). We learned that the <code>.noWS = "outside"</code> argument is crucial for deploying the dashboard with GitHub Actions. It omits extra whitespace around the HTML, which ensures that the dashboard is committed only when the number of videos has changed (rather than creating spurious commits each time data is pulled, even if the number of videos is unchanged).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode markdown md code-with-copy"><code class="sourceCode markdown"><span id="cb13-1">Channels {.sidebar}</span>
<span id="cb13-2">-----------------------------------------------------------------------</span>
<span id="cb13-3"></span>
<span id="cb13-4">The purpose of this dashboard is to provide a running feed of R-Ladies videos posted to YouTube. It is refreshed every 24 hours.</span>
<span id="cb13-5"></span>
<span id="cb13-6">Currently, the feed includes these channels:</span>
<span id="cb13-7"></span>
<span id="cb13-8"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb13-9">dat_join <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb13-10">  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;">arrange</span>(chapter) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb13-11">  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;">distinct</span>(channel_image_url) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb13-12">  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;">pull</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb13-13">  htmltools<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">HTML</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.noWS =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"outside"</span>)</span>
<span id="cb13-14"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
<p>For the main body, I used <a href="https://rstudio.github.io/DT">{DT}</a> to create a table for the information in our clean dataset.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="annotated-cell-15" style="background: #f1f3f5;"><pre class="sourceCode markdown md code-annotation-code code-with-copy code-annotated"><code class="sourceCode markdown"><span id="annotated-cell-15-1">Column {data-width=900}</span>
<span id="annotated-cell-15-2">-----------------------------------------------------------------------</span>
<span id="annotated-cell-15-3"></span>
<span id="annotated-cell-15-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">### By default, the list is sorted by latest video.</span></span>
<span id="annotated-cell-15-5"></span>
<span id="annotated-cell-15-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">style</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="annotated-cell-15-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">.dataTables_scrollBody</span> {</span>
<span id="annotated-cell-15-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">max-height</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">%</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">!important</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="annotated-cell-15-9">}</span>
<span id="annotated-cell-15-10"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">style</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="annotated-cell-15-11"></span>
<span id="annotated-cell-15-12"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="annotated-cell-15-13">dat_dashboard <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-15-14">  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>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>chapter, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>channel_image_url) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="annotated-cell-15-15">  DT<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">datatable</span>(</span>
<span id="annotated-cell-15-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colnames =</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;">"Date"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Channel"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Video"</span>),</span>
<span id="annotated-cell-15-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">filter =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top"</span>,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-15" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-15-18" class="code-annotation-target">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">escape =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-15" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-15-19" class="code-annotation-target">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1000"</span>,</span>
<span id="annotated-cell-15-20">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">elementId =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashboard"</span>,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-15" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-15-21" class="code-annotation-target">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">options =</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;">columnDefs =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="annotated-cell-15-22">      <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;">className =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dt-middle"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">targets =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_all"</span>)</span>
<span id="annotated-cell-15-23">    ))</span>
<span id="annotated-cell-15-24">  )</span>
<span id="annotated-cell-15-25"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-15" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-15" data-code-lines="18" data-code-annotation="1"><code>escape = FALSE</code> renders the URLs within the table as HTML.</span>
</dd>
<dt data-target-cell="annotated-cell-15" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-15" data-code-lines="19" data-code-annotation="2"><code>height = "1000"</code> makes it expand to the entire column height.</span>
</dd>
<dt data-target-cell="annotated-cell-15" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-15" data-code-lines="21" data-code-annotation="3">The list within <code>options</code> aligns the text within columns (in this case, to be in the middle of the cell for all columns).<sup>1</sup></span>
</dd>
</dl>
<p>And that’s it! See the <a href="https://github.com/ivelasq/rladies-video-feed/blob/main/index.Rmd">final dashboard code</a> on GitHub.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/automated-youtube-dashboard/img/dashboard.png" class="img-fluid figure-img" alt="Screenshot of the final dashboard with a sidebar of the R-Ladies channels and the main section showing the table of videos from the various chapters"></p>
<figcaption>Final dashboard</figcaption>
</figure>
</div>
<p><a href="https://ivelasq.github.io/rladies-video-feed/">Try it out</a> — search “Shiny” to see any video with Shiny in the title, or “Ecuador” to see all the videos from R-Ladies Ecuador!</p>
</section>
<section id="create-a-github-action-workflow" class="level2">
<h2 class="anchored" data-anchor-id="create-a-github-action-workflow">Create a GitHub Action workflow</h2>
<p>Great, we have a completed dashboard! Now, what if we want to keep it updated without manually re-knitting the dashboard? The next step is to create a GitHub Action. GitHub Actions are workflows that you create and configure to automate various tasks within your GitHub repositories. They are event-driven and can be triggered by actions such as code commits, pull requests, issue updates, or scheduled intervals.</p>
<section id="create-a-github-action-workflow-file-in-your-project" class="level3">
<h3 class="anchored" data-anchor-id="create-a-github-action-workflow-file-in-your-project">Create a GitHub Action workflow file in your project</h3>
<p>GitHub Actions use <a href="https://yaml.org/">YAML syntax</a> and are saved as <code>.yml</code> or <code>.yaml</code> files within a folder called <code>.github/workflows/</code>. We can use GitHub Actions to create a bot that refreshes the dashboard on a regular basis. You can see an <a href="https://github.com/ivelasq/rladies-video-feed/blob/main/.github/workflows/rladies-videos-bot.yaml">example workflow in the GitHub repository</a>. H/T to <a href="https://github.com/gvelasq"><span class="citation" data-cites="gvelasq">@gvelasq</span></a> and this amazing <a href="https://github.com/r-lib/actions/blob/v2/examples/render-rmarkdown.yaml">example</a> in the <a href="https://github.com/r-lib/actions/tree/v2/examples#readme">r-lib/actions</a> repo for inspiration.</p>
<p>To create a GitHub Action:</p>
<ol type="1">
<li>Create a folder in your repository called <code>.github</code>.</li>
<li>Within <code>.github</code>, add a folder called <code>workflows</code>.</li>
<li>Create a file called <code>rladies-videos-bot.yaml</code>.</li>
<li>Copy and paste the workflow below in <code>rladies-videos-bot.yaml</code>.</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="annotated-cell-16" style="background: #f1f3f5;"><pre class="sourceCode yaml code-annotation-code code-with-copy code-annotated"><code class="sourceCode yaml"><span id="annotated-cell-16-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">on</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="annotated-cell-16-2"><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;">schedule</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-16" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-16-3" class="code-annotation-target"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cron</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;">'0 0 * * *'</span></span>
<span id="annotated-cell-16-4"></span>
<span id="annotated-cell-16-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</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;"> rladies-videos-bot</span></span>
<span id="annotated-cell-16-6"></span>
<span id="annotated-cell-16-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">jobs</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="annotated-cell-16-8"><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;">rladies-videos-bot</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="annotated-cell-16-9"><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;">runs-on</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;"> ubuntu-latest</span></span>
<span id="annotated-cell-16-10"><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;">env</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="annotated-cell-16-11"><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;">GITHUB_PAT</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;"> ${{ secrets.GITHUB_TOKEN }}</span></span>
<span id="annotated-cell-16-12"><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;">YOUTUBE_KEY</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;"> ${{ secrets.YOUTUBE_KEY }}</span></span>
<span id="annotated-cell-16-13"><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;">steps</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="annotated-cell-16-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">uses</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;"> actions/checkout@v3</span></span>
<span id="annotated-cell-16-15"><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;">with</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="annotated-cell-16-16"><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;">fetch-depth</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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="annotated-cell-16-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">uses</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;"> r-lib/actions/setup-pandoc@v2</span></span>
<span id="annotated-cell-16-18"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">uses</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;"> r-lib/actions/setup-r@v2</span></span>
<span id="annotated-cell-16-19"><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;">with</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="annotated-cell-16-20"><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;">use-public-rspm</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="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-16" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-16-21" class="code-annotation-target"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">uses</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;"> r-lib/actions/setup-r-dependencies@v2</span></span>
<span id="annotated-cell-16-22"><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;">with</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-16" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-16-23" class="code-annotation-target"><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;">extra-packages</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;"> soodoku/tuber</span></span>
<span id="annotated-cell-16-24"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</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;"> Render and commit dashboard</span></span>
<span id="annotated-cell-16-25"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">        run</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">: </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">|</span></span>
<span id="annotated-cell-16-26">          Rscript -e 'rmarkdown::render("index.Rmd")'</span>
<span id="annotated-cell-16-27">          git config --local user.name "$GITHUB_ACTOR"</span>
<span id="annotated-cell-16-28">          git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com"</span>
<span id="annotated-cell-16-29">          git add index.html</span>
<span id="annotated-cell-16-30">          git commit -m '[Bot] Render and commit dashboard' || echo "No changes to commit"</span>
<span id="annotated-cell-16-31">          git push origin || echo "No changes to commit"</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-16" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-16" data-code-lines="3" data-code-annotation="1">The workflow uses <a href="https://en.wikipedia.org/wiki/Cron">cron</a> syntax to trigger the workflow to start at midnight every day, running through all the tasks detailed in the workflow: pulling the secret keys, setting up R and required packages, rendering <code>index.Rmd</code>, and committing the resulting <code>index.html</code> file only if there are any changes to commit. Matt Dray’s <a href="https://github.com/matt-dray/dialga">{dialga}</a> package is helpful in building cron expressions.</span>
</dd>
<dt data-target-cell="annotated-cell-16" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-16" data-code-lines="21" data-code-annotation="2">The GitHub Action <a href="https://github.com/r-lib/actions/tree/v2-branch/setup-r-dependencies#setup-r-dependencies"><code>r-lib/actions/setup-r-dependencies@v2</code></a> installs R packages that are declared in a <code>DESCRIPTION</code> file. In our case, since our RStudio project name is not a valid R package name due to the hyphens in <code>rladies-video-feed</code>, we created a <code>DESCRIPTION</code> file using <code>usethis::use_description(check_name = FALSE)</code> and added the dependencies to <code>Imports:</code> below using <code>usethis::use_package()</code> for each required R package.</span>
</dd>
<dt data-target-cell="annotated-cell-16" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-16" data-code-lines="23" data-code-annotation="3">To get <code>r-lib/actions/setup-r-dependencies@v2</code> to install the GitHub version of {tuber}, we specified it using the <code>extra-packages</code> parameter.</span>
</dd>
</dl>
<p>The <code>Imports:</code> section of our <a href="https://github.com/ivelasq/rladies-video-feed/blob/main/DESCRIPTION"><code>DESCRIPTION</code></a> file looks like this:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">Imports<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> </span>
<span id="cb14-2">    bslib,</span>
<span id="cb14-3">    dplyr,</span>
<span id="cb14-4">    DT,</span>
<span id="cb14-5">    flexdashboard,</span>
<span id="cb14-6">    htmltools,</span>
<span id="cb14-7">    httr2,</span>
<span id="cb14-8">    jsonlite,</span>
<span id="cb14-9">    readr,</span>
<span id="cb14-10">    rmarkdown,</span>
<span id="cb14-11">    stringr</span></code></pre></div></div>
</section>
<section id="configure-keys-on-github" class="level3">
<h3 class="anchored" data-anchor-id="configure-keys-on-github">Configure keys on GitHub</h3>
<p>Now that we have the workflow set up, we need to let GitHub know what our YouTube API key is so that it can be accessed each time the workflow is triggered.</p>
<ol type="1">
<li>In your GitHub repository, click the ‘Settings’ tab.</li>
<li>Under ‘Security’ on the left-hand side, click ‘Secrets and variables’ then ‘Actions’.</li>
<li>Click the ‘Secrets’ tab, then click ‘New repository secret’.</li>
<li>Give your new secret the name <code>YOUTUBE_KEY</code> and in the ‘Secret’ textbox, paste your YouTube API key, then select ‘Add secret’.</li>
</ol>
<p>Now your GitHub repository is configured to run the workflow script. Your GitHub Action is ready to go!</p>
</section>
</section>
<section id="host-the-dashboard" class="level2">
<h2 class="anchored" data-anchor-id="host-the-dashboard">Host the dashboard</h2>
<p>To host the dashboard, I used GitHub Pages. In the GitHub repository for your dashboard, go to ‘Settings’, then ‘Pages’. Choose the branch and folder of your flexdashboard <code>index.html</code> output file, click ‘Save’, and then you will have a URL to showcase your work.</p>
<p>Here is the final link for this dashboard: <a href="https://ivelasq.github.io/rladies-video-feed">https://ivelasq.github.io/rladies-video-feed</a>.</p>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>In summary, we have explored the powerful combination of {flexdashboard}, GitHub Actions (via <code>r-lib/actions</code>), and {tuber} to create an automated YouTube dashboard.</p>
<ul>
<li>With {flexdashboard}’s customizability and R Markdown support, we can create a visually appealing, interactive dashboard.</li>
<li>The {tuber} package’s integration with the YouTube Data API and new functions we contributed to permit YouTube API key authentication allow us to easily fetch data and keep track of YouTube videos.</li>
<li>With the automation capabilities of GitHub Actions, we can schedule dashboard updates and stay up-to-date with new YouTube videos.</li>
</ul>
<p>It took a while, but we got there! Many thanks to <a href="https://github.com/gvelasq"><span class="citation" data-cites="gvelasq">@gvelasq</span></a>’s support in getting this through the finish line.</p>
<p>Give this tutorial a try and unlock the potential of automated dashboards for your favorite YouTube channels! I’d love to see what you create!</p>
<section id="coda" class="level3">
<h3 class="anchored" data-anchor-id="coda">Coda</h3>
<p>If you made it all the way to the end of this tutorial, I need to plug (as an employee of Posit, formerly RStudio 😁): <a href="https://posit.co/products/enterprise/connect/">Posit Connect</a>! Posit Connect is a platform that allows you to publish and share data products like Quarto docs, Shiny apps, and – you guessed it – dashboards made with {flexdashboard}!</p>
<p>Automating reports and dashboards is easy on Posit Connect. The scheduler is built into the interface and can be adjusted to your specifications. <em>Never write another Cron job again</em>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/automated-youtube-dashboard/img/posit-connect.gif" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<p>Since this is a pet project, I opted not to use Posit Connect, but it certainly was tempting…😇</p>
<center>
<i>Liked this article? I’d love for you to share!</i>
</center>
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs"><li class="nav-item"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" aria-controls="tabset-1-1" aria-selected="true" href="">Twitter</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" aria-controls="tabset-1-2" aria-selected="false" href="">Mastodon</a></li></ul>
<div class="tab-content">
<div id="tabset-1-1" class="tab-pane active" aria-labelledby="tabset-1-1-tab">
<p></p><div id="tweet-33434"></div><script>tweet=<!DOCTYPE html>
<html lang="en" class="dog">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>X / ?</title>
    <meta name="version" content="1">
    <link href="https://abs.twimg.com/favicons/twitter.3.ico" rel="shortcut icon" type="image/x-icon">
    <link rel="stylesheet" href="https://abs.twimg.com/errors/fullscreen_errors-047ca1475a6efac7c9c89a9ff92b7a20.css">
  </head>
  <body dir="auto">
    <div class="top">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1519 200">
        <defs/>
        <path d="M708 103l9-5 13 1 2-2 5 1h8l1-1 42-5h7l7 3v1l12-2a9368 9368 0 0129-6l2-5 12 1 6-2 3 1 2 1v-2l13-2v1l4 2 7-1h1l17-3 1 2 4-1 18-7 3-1 4-1h9l13-1 1-4 3-2 13 1v2l22-2 10-3h6l10 5 16-5 15-3 2-1 8-4 6-2 12-1 7-2 8 5 7 1 22-9h7l5-1v-1l25-3 1 2 5 2v1h11l2 1 8-4h3l-1 1h11l10-6 6 3 9-1 4-1 1 1 1-2 6-1 1-1 10-2h2l7-5v1h4l3-1c11 0 23 2 34-3 2-2 7 0 10 0l12 1 4 1 9 2 12-1 11-3 11 1h4l10-6 17 1 2 1c9 2 19-3 22-11l1-1 9 1 15-5c3-1 9 4 9-5 5 0 5 3 5 7l2 3 4-1 4-2 9-4 3-3h3l8-4 6-3 26 2 7-4h18l7 1c10 3 13-6 17-12l8 4 3-1 14-3 15-2a38 38 0 01-5-1l-8-4 7-8 8-4-10-136-922 71 16 205z"/>
        <path d="M-36 193l9-5 13 1 2-2 5 1h8l1-1 42-5h7l7 3v1l12-2a9328 9328 0 0129-6l2-5 12 1 6-2 3 1 2 1v-2l13-2v1l4 2 7-1h1l17-3 1 2 4-1 18-7 3-1 4-1h9l13-1 1-4 3-2 13 1v2l22-2 10-3h6l10 5 16-5 15-3 2-1 8-4 6-2 12-1 7-2 8 5 7 1 22-9h7l5-1v-1l25-3 1 2 5 2v1h11l2 1 8-4h3l-1 1h9a6 6 0 002 0l10-6 6 3 9-1 4-1a6 6 0 001 1l1-2 6-1 1-1 10-2h2l7-5v1h4l3-1c11 0 23 2 34-3 2-2 7 0 10 0l12 1 4 1 9 2 12-1 11-3 11 1h4l10-6 17 1 2 1c9 2 19-3 22-11l1-1 9 1 15-5c3-1 9 4 9-5 5 0 5 3 5 7l2 3 4-1 4-2 9-4 3-3h3l8-4 6-3 26 2 7-4h18l7 1c10 3 13-6 17-12l8 4 3-1 14-3 15-2a37 37 0 01-5-1l-8-4 7-8 8-4-10-136-922 71 16 205z"/>
      </svg>
    </div>
    <div class="container">
      <div class="content">
        <a href="https://twitter.com" title="X logo">
          <svg viewBox="0 0 24 24" aria-hidden="true" class="x-logo"><g><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path></g></svg>
        </a>
        <h1 id="header">Nothing to see here</h1>
        <p id="description">Looks like this page doesn’t exist. Here’s a picture of a poodle sitting in a chair for your trouble.</p>

          <a id="button_search" href="/" class="button">Looking for this?</a>

      </div>
      <img id="image" src="https://abs.twimg.com/errors/ErrorState_NotFound.png" alt="A primped poodle with a bow in its hair sitting in a chair like a human.">
      <div class="footer">
        <ul>
          <li><a href="https://twitter.com/" id="footer_home">Home</a></li>
          <li><a href="https://status.twitterstat.us/" id="footer_status">Status</a></li>
          <li><a href="https://twitter.com/tos" id="footer_tos">Terms of Service</a></li>
          <li><a href="https://twitter.com/privacy" id="footer_privacy">Privacy Policy</a></li>
          <li><a href="https://support.twitter.com/articles/20170514" id="footer_cookie">Cookie Policy</a></li>
          <li><a href="https://legal.twitter.com/imprint" id="footer_imprint">Imprint</a></li>
          <li><a href="https://business.twitter.com/en/help/troubleshooting/how-twitter-ads-work.html" id="footer_ads">Ads info</a></li>
          <li dir="ltr">&copy; X Corp. <span id="copyright-year">&emsp;&emsp;&emsp;&emsp;</span></li>
        </ul>
      </div>
    </div>
  </body>
  <script src="https://abs.twimg.com/errors/404-8651f633fd193e0b546010676a4fac06.js"></script>

;document.getElementById("tweet-33434").innerHTML = tweet["html"];<p></p>
</div>
<div id="tabset-1-2" class="tab-pane" aria-labelledby="tabset-1-2-tab">
<center>
<iframe src="https://fosstodon.org/@ivelasq3/110822815087956079/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen">
</iframe>
<script src="https://fosstodon.org/embed.js" async="async"></script>
</center>
</div>
</div>
</div>


</section>
</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>I found out about this here: <a href="https://stackoverflow.com/questions/35749389/column-alignment-in-dt-datatable">https://stackoverflow.com/questions/35749389/column-alignment-in-dt-datatable</a>.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/automated-youtube-dashboard/</guid>
  <pubDate>Mon, 31 Jul 2023 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/automated-youtube-dashboard/img/thumbnail.jpeg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Setting up macOS as an R data science rig in 2023</title>
  <dc:creator>Isabella Velásquez</dc:creator>
  <dc:creator>Gustavo E. Velásquez</dc:creator>
  <link>https://ivelasq.rbind.io/blog/macos-rig/</link>
  <description><![CDATA[ 




<section id="tldr" class="level2">
<h2 class="anchored" data-anchor-id="tldr">TL;DR</h2>
<p>In this post, we cover our preferred setup for R on macOS going into 2023. We highlight these awesome tools: <a href="https://brew.sh/">Homebrew</a>, <a href="https://git-scm.com/download/linux">Git</a>, <a href="https://zsh.sourceforge.io/">zsh</a>, <a href="https://ohmyz.sh/#install">Oh My Zsh</a>, <a href="https://github.com/r-lib/rig">rig</a>, the R packages {<a href="https://usethis.r-lib.org/">usethis</a>} and {<a href="https://gitcreds.r-lib.org/">gitcreds</a>}, and <a href="https://quarto.org">Quarto</a>.</p>
<p>If you prefer to look at a short list than read through a long-form blog post, much of the information below is summarized in this <a href="https://github.com/gvelasq/dotfiles/tree/main/macos">dotfiles</a> repository. Keeping your own <a href="https://dotfiles.github.io">dotfiles</a> repository, or bookmarking this post or <a href="https://www.garrickadenbuie.com/blog/setting-up-a-new-macbook-pro">others</a>, will help you stay sane next time you are setting yourself up for data science in R on a brand new macOS installation.</p>
<ul>
<li>The Problem</li>
<li>Installation</li>
<li>Final Thoughts</li>
<li>Related Work</li>
</ul>
</section>
<section id="the-problem" class="level2">
<h2 class="anchored" data-anchor-id="the-problem">The Problem</h2>
<p>Like a new year 🗓️, a new computer 🖥️ (or a fresh reinstall) can bring so many opportunities. A clear desktop! So much memory! And then you remember that you have to install and configure all of your programs again, and that initial excitement gives way to despair and hopelessness. 😱</p>
<p>Okay, that’s a bit of an exaggeration, 🤭 but it can be tedious to reconfigure your setup the way that you like it. However, by using dotfiles, or hidden configuration files (whose names start with a dot/period, which on macOS hides them from view in the Finder), you can store your user preferences on a hosted version control service like <a href="https://github.com/">GitHub</a>. By dropping dotfiles in the correct directory, you can access and reuse your exact configuration and settings across machines, saving time and hassle. ♻️</p>
<p>In this post, we’ll share some helpful dotfiles for all you RStudio users who are rocking a new macOS 🍎 installation in 2023. This post is geared towards you if:</p>
<ul>
<li>You’ve been installing R and RStudio on macOS and setting them up in your own way already, but either forget the many steps (Git, etc.) or are always having to relearn them;</li>
<li>You do a lot of point-and-click downloading of files for installation, and have been considering jumping into command-line adventures 👩🏻‍💻 with Homebrew;</li>
<li>You’ve never heard of rig;</li>
<li>You want a one-stop-shop for setting up your rig next time;</li>
<li>You have a well-oiled, well-defined workflow but are interested in seeing how others set up their machines, to perhaps learn something new!</li>
</ul>
<p>Since it is the year of <a href="https://openai.com/blog/chatgpt/">ChatGPT</a>, we did ask its suggested setup. We thought we could do better (at least for now, maybe not in 2024)! 🤗</p>
<p>Let’s fall into a <a href="https://blog.codinghorror.com/falling-into-the-pit-of-success">pit of success</a> <sup>TM</sup> (when configuring macOS)!</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://imgur.com/7J1bEaJ.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Hadley Wickham miming typing; in the background is a presentation that says My goal is to make a pit of success" width="400"></p>
</figure>
</div>
</section>
<section id="installation" class="level2">
<h2 class="anchored" data-anchor-id="installation">Installation</h2>
<p>We’re going to use <a href="https://brew.sh">Homebrew</a> to facilitate installation steps on macOS. Homebrew styles itself as ‘the missing package manager for macOS.’</p>
<ol type="1">
<li>Open Applications &gt; Utilities &gt; Terminal. Install Homebrew using the terminal command below, also provided on the Homebrew landing page. Paste this code into your terminal and hit enter:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/bin/bash</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-fsSL</span> https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span></code></pre></div></div>
<ol start="2" type="1">
<li>Install <a href="https://git-scm.com">Git</a>. This version control system is going to come in handy for future projects on your new installation.</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install git</span></code></pre></div></div>
<ol start="3" type="1">
<li>Configure <a href="https://github.com/gvelasq/git-reference#setup">global Git settings</a>.</li>
</ol>
<p>Run the code below (replacing the text in the quotation marks with your information) to adjust your Git settings.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">git</span> config <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--global</span> user.name <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;full-name&gt;"</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">git</span> config <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--global</span> user.email <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;email&gt;"</span></span></code></pre></div></div>
<ol start="4" type="1">
<li>Install <a href="https://zsh.sourceforge.io">zsh</a>.</li>
</ol>
<p>Several years back, macOS switched from using the bash shell to using zsh as the default shell. Installing the latest version of zsh from Homebrew gives you the <em>latest</em> version — otherwise, zsh and Git are both stuck at the version bundled the last time you updated macOS — which makes them open to vulnerabilities and/or don’t have the latest features.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install zsh</span></code></pre></div></div>
<ol start="5" type="1">
<li>Install <a href="https://ohmyz.sh/#install">Oh My Zsh</a>.</li>
</ol>
<p>Oh My Zsh (OMZ) is ‘a delightful &amp; open source framework for Zsh.’ Or as ChatGPT succinctly put it:</p>
<p></p><div id="tweet-45971"></div><script>tweet={"url":"https:\/\/twitter.com\/robbyrussell\/status\/1599596073282342914","author_name":"Robby Russell","author_url":"https:\/\/twitter.com\/robbyrussell","html":"\u003Cblockquote class=\"twitter-tweet\" align=\"center\"\u003E\u003Cp lang=\"en\" dir=\"ltr\"\u003ESo sweet. \u003Ca href=\"https:\/\/twitter.com\/hashtag\/ChatGPT?src=hash&amp;ref_src=twsrc%5Etfw\"\u003E#ChatGPT\u003C\/a\u003E \u003Ca href=\"https:\/\/t.co\/DoVNbUStmE\"\u003Epic.twitter.com\/DoVNbUStmE\u003C\/a\u003E\u003C\/p\u003E&mdash; Robby Russell (@robbyrussell) \u003Ca href=\"https:\/\/twitter.com\/robbyrussell\/status\/1599596073282342914?ref_src=twsrc%5Etfw\"\u003EDecember 5, 2022\u003C\/a\u003E\u003C\/blockquote\u003E\n\u003Cscript async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"\u003E\u003C\/script\u003E\n\n","width":550,"height":null,"type":"rich","cache_age":"3153600000","provider_name":"Twitter","provider_url":"https:\/\/twitter.com","version":"1.0"};document.getElementById("tweet-45971").innerHTML = tweet["html"];</script><p></p>
<p>It comes with a ton of plugins, themes, and functions. For most users, having the great themes available from OMZ are enough to switch. But for us, the real value is <a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins">all the built-in OMZ plugins</a> — which provide a rich set of aliases for Homebrew, Git, and many other command-line programs. For example, <code>gs</code> is <code>git status</code>, <code>bubo</code> is <code>brew update &amp;&amp; brew outdated</code> (very helpful), etc. Here are some you should know:</p>
<ul>
<li>The <a href="https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/brew">brew</a> plugin and its aliases</li>
<li>The <a href="https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/git">git</a> plugin</li>
<li>The <a href="https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/macos">macos</a> plugin for easier living through the Terminal</li>
<li>There’s even a plugin that <a href="https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/aliases">reminds you what your aliases are</a>! – for maximum discoverability</li>
</ul>
<p>You can also hand-code your themes into your <code>.zshrc</code> dotfile instead of using the OMZ themes. The aliases not provided by OMZ can be added to the <code>custom.zsh</code> dotfile, such as the ones in the dotfiles linked below.</p>
<p>Install OMZ with:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sh</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-fsSL</span> https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span></code></pre></div></div>
<ol start="6" type="1">
<li>Configure <a href="https://github.com/gvelasq/dotfiles/tree/main/zsh">Oh My Zsh</a>.</li>
</ol>
<p>To configure oh-my-zsh, you can:</p>
<ol type="1">
<li><strong>Edit your settings: </strong>Navigate to your home directory <code>~/</code> and edit the <code>.zshrc</code> file.</li>
<li><strong>Use preconfigured settings: </strong>Navigate to your home directory <code>~/</code>. Replace the default <code>.zshrc</code> file with <a href="https://github.com/gvelasq/dotfiles/blob/main/zsh/.zshrc">this file</a>. Then, navigate to the hidden folder <code>~/.oh-my-zsh/custom</code> and drop <a href="https://github.com/gvelasq/dotfiles/blob/main/zsh/custom.zsh">this file</a> in the folder.</li>
</ol>
<div class="callout callout-style-default callout-tip callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>On a Mac, you can press Command + Shift + . to see your hidden folders.</p>
</div>
</div>
<p>A <code>custom.zsh</code> file might be helpful because you can add many more commands for OMZ plugins than what are built in. For instance,</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> bog=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brew outdated --greedy"</span></span></code></pre></div></div>
<p>This allows you to use <code>bog</code> to run <code>brew outdated --greedy</code>, instead of having to type the whole command out. That particular command is helpful if you want to find ALL the programs that could potentially be upgraded.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/macos-rig/image1.jpg" class="img-fluid quarto-figure quarto-figure-center figure-img" data-fig-width="400" alt="Keep Calm and bubo bog bupc bc"></p>
</figure>
</div>
<ol start="7" type="1">
<li>Go back to the Terminal and install <a href="https://github.com/r-lib/rig#macos-homebrew">rig</a>.</li>
</ol>
<p><a href="https://github.com/r-lib/rig">rig</a>, the ‘R Installation Manager,’ is an amazing tool. It not only lets you download R, but install, configure, switch between, and remove <em>multiple</em> R versions. It also allows you to manage <em>user-level package libraries</em> (meaning you can delete a version of R without losing all your packages!). Mara Averick wrote a great summary on <a href="https://mara.quarto.pub/tidy-advent-2022/posts/10-rig.html">Day 10 of Tidy Advent 2022</a>.</p>
<p>Install rig by running these commands in the Terminal:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> tap r-lib/rig</span>
<span id="cb7-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cask</span> rig</span></code></pre></div></div>
<ol start="8" type="1">
<li>Install <a href="https://www.r-project.org">R</a>.</li>
</ol>
<p>Install the latest version of R using rig:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">rig</span> add release</span></code></pre></div></div>
<ol start="9" type="1">
<li>Install <a name="abcd"></a><a href="https://posit.co/download/rstudio-desktop">RStudio Desktop</a>.</li>
</ol>
<p>You want the latest and greatest RStudio, no? Use Homebrew to download and install the latest version. Once a new version is released, the community is very quick at updating the cask entry for RStudio in Homebrew.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cask</span> rstudio</span></code></pre></div></div>
<ol start="10" type="1">
<li>Configure <a href="https://github.com/gvelasq/dotfiles/blob/main/R/.Rprofile"><code>.Rprofile</code></a>.</li>
</ol>
<p>In RStudio, install the {<a href="https://usethis.r-lib.org/">usethis</a>} package, a tremendous tool for increased productivity with your R projects. In other words, you should use {usethis}. 😀</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"usethis"</span>)</span></code></pre></div></div>
<p>Once installed, open your <code>.Rprofile</code> by running:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">usethis<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">edit_r_profile</span>()</span></code></pre></div></div>
<p><a href="https://github.com/gvelasq/dotfiles/blob/main/R/.Rprofile">Here’s an example of an <code>.Rprofile</code> script.</a> This script [1] sets {devtools} and {usethis} to load with each R session (to write <code>install_github()</code> without a <code>library(devtools)</code>), [2] sets <a href="https://packagemanager.rstudio.com/client/#/">Posit Public Package Manager (P3M)</a> as the default repo for Linux (not relevant for this macOS guide), [3] sets a bunch of {usethis} defaults for package development which need to be overridden with personal details for each person, [4] sets <code>vsc.rstudioapi = TRUE</code> for VS Code (again not relevant for this guide), [5] sets several strict warnings which are helpful when developing packages (e.g., not using partial argument matching).</p>
<p>For your rig configuration, you would create a similar script, edit the <code>.Rprofile</code>, and restart the session.</p>
<ol start="11" type="1">
<li>Configure <a href="https://github.com/gvelasq/dotfiles/tree/main/rstudio">RStudio</a>.</li>
</ol>
<p><a href="https://support.posit.co/hc/en-us/articles/204463668-Code-Snippets-in-the-RStudio-IDE">Snippets</a> help quickly insert common short pieces of code. Open RStudio’s snippet config for R scripts:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">usethis<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">edit_rstudio_snippets</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>)</span></code></pre></div></div>
<p>Append <a href="https://github.com/gvelasq/dotfiles/blob/main/rstudio/r.snippets">this script</a> to the bottom of the file for some useful examples.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Change the prefix of your snippets to your initials. The default in these examples is <code>gv</code>.</p>
</div>
</div>
<p>Try a snippet out! After appending the script to your snippet file, type <code>dml</code> in the Console and press tab:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/macos-rig/gif1.gif" class="img-fluid figure-img" alt="Typing dml in the RStudio Console pane and then pressing tab to enable a snippet that lists out De Morgan's laws."></p>
<figcaption>For whenever you want to remember De Morgan’s laws. 😉</figcaption>
</figure>
</div>
<p>Now, open RStudio’s preference file by running:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">usethis<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">edit_rstudio_prefs</span>()</span></code></pre></div></div>
<p>Add the content of <a href="https://github.com/gvelasq/dotfiles/blob/main/rstudio/rstudio-prefs.json">this file</a> to the <code>rstudio-prefs.json</code> file. This file configures RStudio to look and act the way that you’d like (rainbow parentheses, anybody?). 🌈</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<ul>
<li>Change <code>default_project_location</code> to your preferred directory. The default in this example is <code>~/code</code>.</li>
<li>Change <code>git_exe_path</code> to the location of your Git executable, which can be found by typing <code>which git</code> in a terminal. The default in this example is <code>/usr/local/bin/git</code>.</li>
<li>Change document_author to your name. The default in this example is <code>gvelasq</code>.</li>
</ul>
</div>
</div>
<p>Finally, add the contents of <a href="https://github.com/gvelasq/dotfiles/blob/main/rstudio/rstudio_bindings.json"><code>rstudio_bindings.json</code></a> to the local version found in this hidden folder (I don’t think there’s a {usethis} command for this, unfortunately!):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb14-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">~/.config/rstudio/keybindings/rstudio_bindings.json</span></span></code></pre></div></div>
<p>Now, anytime you want to make sure you’re using the most current version of RStudio, you just have to run <kbd>Shift</kbd>+<kbd>Cmd</kbd>+<kbd>R</kbd>!</p>
<ol start="12" type="1">
<li>Set Git credentials in R.</li>
</ol>
<p>The {<a href="https://gitcreds.r-lib.org/">gitcreds</a>} package allows you to set your GitHub token once and use it everywhere (Git, R, and the RStudio IDE). Use it to set up RStudio with a <a href="https://happygitwithr.com/https-pat.html#store-pat">Personal Access Token</a> (PAT) with GitHub and have it work every time.</p>
<p>Install the {gitcreds} package:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gitcreds"</span>)</span></code></pre></div></div>
<p>Then, run <code>usethis::create_github_token()</code> to open a browser window to the GitHub form to generate a PAT with suggested, pre-selected scopes. This helps you make the right choice of scopes every time.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb16-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">usethis::create_github_token()</span></span></code></pre></div></div>
<p>Then, the command will suggest to use <code>gitcreds::gitcreds_set()</code> to save the PAT locally using the macOS Git credential manager (after copying it from GitHub):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1">gitcreds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gitcreds_set</span>()</span></code></pre></div></div>
<ol start="13" type="1">
<li>Install <a href="https://quarto.org/docs/get-started/">Quarto</a>.</li>
</ol>
<p>Quarto is a (kinda new) open-source scientific and technical publishing system built on Pandoc. It allows you to create dynamic content with R and Python, like documents, websites (like this blog!), and <a href="https://ivelasq.rbind.io/talk/intro-to-quarto/">presentations</a>.</p>
<p>Quarto comes bundled with RStudio v. 2022.07 and later, so the installation in step 9 above should have this covered. But, if you’d like to install Quarto yourself, run this in your Terminal:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb18-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cask</span> quarto</span></code></pre></div></div>
<p>You’ve done it! Congratulations on your configured, custom R data science setup.</p>
</section>
<section id="final-thoughts" class="level2">
<h2 class="anchored" data-anchor-id="final-thoughts">Final Thoughts</h2>
<p>We hope that this post is helpful in setting up an R data science rig on macOS! We know there were a lot of steps. In summary:</p>
<ul>
<li>Dotfiles are hidden configuration files where you can store your user preferences and use them across machines and installations.</li>
<li>The configuration steps above ensure that you’re using the best tools for the macOS terminal: Homebrew (for package management) and zsh (for execution).</li>
<li>They also ensure you’re using the best tools for running analyses: Git (for version control), rig (for R versioning), R (the best programming language [in our humble opinion]), RStudio (the GOAT), {usethis} (for project setup and development), {gitcreds} (for managing Git), and Quarto (for content creation and publishing).</li>
<li>Tools like OMZ and snippets help you use aliases that make running your workflow easier to remember.</li>
</ul>
<p>We know there are a ton of ways of setting up a data science rig, and we’d love to learn about your dotfile repositories, best practices, or favorite workflow packages on Twitter/Mastodon!</p>
</section>
<section id="related-work" class="level2">
<h2 class="anchored" data-anchor-id="related-work">Related Work</h2>
<ul>
<li><a href="https://github.com/hrbrmstr/RSwitch">RSwitch</a> was a menubar app that let you switch between different R versions; it is now archived.</li>
<li><span class="citation" data-cites="grrrck">@grrrck</span>’s <a href="https://www.garrickadenbuie.com/blog/setting-up-a-new-macbook-pro">guide</a>, published in 2020, documents an epic adventure of setting up a Macbook Pro.</li>
<li>{<a href="https://pak.r-lib.org/">pak</a>} is an awesome R package and the only reason we didn’t use it is <a href="https://github.com/r-lib/pak/issues/436">because it doesn’t yet work with renv</a>. Since we use {<a href="https://rstudio.github.io/renv/articles/renv.html">renv</a>}, we’re holding off on {pak} for now, but we do look forward to using both tools together!</li>
</ul>
</section>
<section id="chat-gpt" class="level2">
<h2 class="anchored" data-anchor-id="chat-gpt">Where we have ChatGPT write our blog post for us</h2>
<p>Here’s ChatGPT’s not bad (but still unnerving) response to: ‘Write a blog post, for a technical blog about the R programming language, entitled “Setting up macOS as an R data science rig in 2023.” Include installation and configuration examples for Homebrew, Git, zsh, oh-my-zsh, R, RStudio, and Quarto.’</p>
<details>
<summary>
See response.
</summary>
<p><i> As a data scientist, it is important to have a reliable and efficient setup for your work environment. In this tutorial, we will walk through the steps of setting up macOS as an R data science rig in 2023. We will cover the installation and configuration of Homebrew, Git, zsh, oh-my-zsh, R, RStudio, and Quarto. By the end of this tutorial, you will have a fully functional and customizable R development environment on your Mac.</i></p><i>
<p>Step 1: Install Homebrew</p>
<p>Homebrew is a package manager for macOS that makes it easy to install and manage software on your Mac. To install Homebrew, open a terminal window and paste the following command:</p>
<pre><code>/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</code></pre>
<p>Hit enter and follow the prompts to complete the installation.</p>
<p>Step 2: Install Git</p>
<p>Git is a version control system that allows you to track changes to your code and collaborate with others. To install Git using Homebrew, run the following command in the terminal:</p>
<pre><code>brew install git</code></pre>
<p>Step 3: Install zsh and oh-my-zsh</p>
<p>zsh is a shell (command line interface) that allows you to execute commands on your computer. oh-my-zsh is a framework for managing your zsh configuration. To install zsh and oh-my-zsh, run the following commands in the terminal:</p>
<pre><code>brew install zsh

sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"</code></pre>
<p>Step 4: Install R</p>
<p>To install the latest version of R on your Mac, run the following command in the terminal:</p>
<pre><code>brew install r</code></pre>
<p>Step 5: Install RStudio</p>
<p>RStudio is a popular integrated development environment (IDE) for R. To install RStudio, visit the RStudio website (https://rstudio.com/) and download the latest version for Mac. Once the download is complete, open the downloaded file and follow the prompts to complete the installation.</p>
<p>Step 6: Install Quarto</p>
<p>Quarto is a powerful tool for creating reproducible research documents in R. To install Quarto, run the following command in the terminal:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb23-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quarto"</span>)</span></code></pre></div></div>
<p>Conclusion:</p>
</i><p><i>By following the steps outlined in this tutorial, you should now have a fully functional and customizable R development environment on your Mac. With Homebrew, Git, zsh, oh-my-zsh, R, RStudio, and Quarto installed and configured, you are ready to start your data science journey with R on macOS. Happy coding!</i></p>
We told you it was unnerving 👀
</details>


</section>

 ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/macos-rig/</guid>
  <pubDate>Thu, 22 Dec 2022 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/macos-rig/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Three packages that port the tidyverse to Python</title>
  <link>https://ivelasq.rbind.io/blog/tidyverse-python-ports/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidyverse-python-ports/thumbnail-wide.jpg" class="img-fluid figure-img" alt="A woman holding an instrument while a man who is facing away from us paints her, the room has luxurious decorations."></p>
<figcaption>Johannes Vermeer, The Allegory of Painting (1666)</figcaption>
</figure>
</div>
<p>As I’ve been saying every year for the past seven years or so, I am learning Python. (It’s been a journey.)</p>
<p>Python packages like pandas have several ways to work with data. There are several options for indexing, slicing, etc. They have a lot of flexibility but also a lot of conventions to remember.</p>
<p>I am familiar with the grammar of the <a href="https://www.tidyverse.org/">tidyverse</a>, which provides a consistent set of verbs to solve common data manipulation challenges. I investigated ways to port tidyverse-like verbs to Python (hopefully making Python a little easier to grasp).</p>
<p>Here are three packages that do just that.</p>
<section id="siuba" class="level2">
<h2 class="anchored" data-anchor-id="siuba">siuba</h2>
<p>The <a href="https://github.com/machow/siuba">siuba</a> package, created by <a href="https://twitter.com/chowthedog">Michael Chow</a>, allows you to use dplyr-like syntax with pandas. Siuba ports over several functions, including <code>select()</code>, <code>filter()</code>, <code>mutate()</code>, <code>summarize()</code>, and <code>arrange()</code>. The package also allows you to use <code>group_by()</code> and a <code>&gt;&gt;</code> pipe.</p>
<p>Let’s check out a few examples using the palmerpenguins dataset (<a href="https://allisonhorst.github.io/palmerpenguins/">R</a>, <a href="https://github.com/mcnakhaee/palmerpenguins">Python</a>).</p>
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs"><li class="nav-item"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" aria-controls="tabset-1-1" aria-selected="true" href="">Python</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" aria-controls="tabset-1-2" aria-selected="false" href="">R</a></li></ul>
<div class="tab-content">
<div id="tabset-1-1" class="tab-pane active" aria-labelledby="tabset-1-1-tab">
<div id="a9d032bb" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> palmerpenguins <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> load_penguins</span>
<span id="cb1-2">penguins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_penguins()</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> siuba <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> group_by, summarize, _</span>
<span id="cb1-4"></span>
<span id="cb1-5">(penguins</span>
<span id="cb1-6">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> group_by(_.species)</span>
<span id="cb1-7">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> summarize(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> _.species.count())</span>
<span id="cb1-8">)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">species</th>
<th data-quarto-table-cell-role="th">n</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>Adelie</td>
<td>152</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>Chinstrap</td>
<td>68</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>Gentoo</td>
<td>124</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div>
<div id="tabset-1-2" class="tab-pane" aria-labelledby="tabset-1-2-tab">
<div class="code-copy-outer-scaffold"><div class="sourceCode" 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;">library</span>(palmerpenguins)</span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb2-3"></span>
<span id="cb2-4">(penguins <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb2-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(species) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb2-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarize</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>()))</span></code></pre></div></div>
<pre><code># A tibble: 3 × 2
  species       n
  &lt;fct&gt;     &lt;int&gt;
1 Adelie      152
2 Chinstrap    68
3 Gentoo      124</code></pre>
</div>
</div>
</div>
<p>Thanks to the <a href="https://siuba.readthedocs.io/en/latest/">documentation</a> and <a href="https://learn.siuba.org/intro-data-science/01">interactive tutorials</a> available for siuba, it’s easy to see the parallels and differences with dplyr so that you can craft these data manipulation tasks yourself.</p>
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs"><li class="nav-item"><a class="nav-link active" id="tabset-2-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-1" aria-controls="tabset-2-1" aria-selected="true" href="">Python</a></li><li class="nav-item"><a class="nav-link" id="tabset-2-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-2-2" aria-controls="tabset-2-2" aria-selected="false" href="">R</a></li></ul>
<div class="tab-content">
<div id="tabset-2-1" class="tab-pane active" aria-labelledby="tabset-2-1-tab">
<div id="f0288ada" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> palmerpenguins <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> load_penguins</span>
<span id="cb4-2">penguins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_penguins()</span>
<span id="cb4-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> siuba <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> select</span>
<span id="cb4-4"></span>
<span id="cb4-5">(penguins</span>
<span id="cb4-6">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> select(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>_.isalpha(), _.species)</span>
<span id="cb4-7">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> group_by(_.species)</span>
<span id="cb4-8">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> summarize(</span>
<span id="cb4-9">      bill_length_mm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> _.bill_length_mm.mean(),</span>
<span id="cb4-10">      bill_depth_mm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> _.bill_depth_mm.mean(),</span>
<span id="cb4-11">      flipper_length_mm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> _.flipper_length_mm.mean(),</span>
<span id="cb4-12">      body_mass_g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> _.body_mass_g.mean()</span>
<span id="cb4-13">  )</span>
<span id="cb4-14">)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">species</th>
<th data-quarto-table-cell-role="th">bill_length_mm</th>
<th data-quarto-table-cell-role="th">bill_depth_mm</th>
<th data-quarto-table-cell-role="th">flipper_length_mm</th>
<th data-quarto-table-cell-role="th">body_mass_g</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>Adelie</td>
<td>38.791391</td>
<td>18.346358</td>
<td>189.953642</td>
<td>3700.662252</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>Chinstrap</td>
<td>48.833824</td>
<td>18.420588</td>
<td>195.823529</td>
<td>3733.088235</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>Gentoo</td>
<td>47.504878</td>
<td>14.982114</td>
<td>217.186992</td>
<td>5076.016260</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div>
<div id="tabset-2-2" class="tab-pane" aria-labelledby="tabset-2-2-tab">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">(penguins <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb5-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(species) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb5-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarize</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">across</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;">where</span>(is.character), mean, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)))</span></code></pre></div></div>
<pre><code># A tibble: 3 × 8
  species   island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
  &lt;fct&gt;      &lt;dbl&gt;          &lt;dbl&gt;         &lt;dbl&gt;             &lt;dbl&gt;       &lt;dbl&gt;
1 Adelie        NA           38.8          18.3              190.       3701.
2 Chinstrap     NA           48.8          18.4              196.       3733.
3 Gentoo        NA           47.5          15.0              217.       5076.
# … with 2 more variables: sex &lt;dbl&gt;, year &lt;dbl&gt;</code></pre>
</div>
</div>
</div>
</section>
<section id="plotnine" class="level2">
<h2 class="anchored" data-anchor-id="plotnine">plotnine</h2>
<p>The <a href="https://github.com/has2k1/plotnine">plotnine</a> package, created by <a href="https://twitter.com/HKibirige">Hassan Kibirige</a>, lets you use a grammar of graphics for Python.</p>
<p>You can use siuba and plotnine together, similar to how you would use dplyr and ggplot2 together.</p>
<div id="15369332" class="cell" data-dpi="300" data-message="false" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> siuba <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb7-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> plotnine <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb7-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> palmerpenguins <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> load_penguins</span>
<span id="cb7-4">penguins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_penguins()</span>
<span id="cb7-5"></span>
<span id="cb7-6">(penguins</span>
<span id="cb7-7"> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># using siuba pipe</span></span>
<span id="cb7-8"> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> ggplot(aes(x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flipper_length_mm'</span>, y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'body_mass_g'</span>))</span>
<span id="cb7-9"> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># creating plotnine plot</span></span>
<span id="cb7-10">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> geom_point(aes(color <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'species'</span>, shape <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'species'</span>),</span>
<span id="cb7-11">             size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="cb7-12">             alpha <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>)</span>
<span id="cb7-13">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> theme_minimal()</span>
<span id="cb7-14">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> labs(title <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Penguin size, Palmer Station LTER"</span>,</span>
<span id="cb7-15">         subtitle <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Flipper length and body mass for Adelie, Chinstrap, and Gentoo Penguins"</span>,</span>
<span id="cb7-16">        x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Flipper length (mm)"</span>,</span>
<span id="cb7-17">        y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Body mass (g)"</span>,</span>
<span id="cb7-18">        color <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Penguin species"</span>,</span>
<span id="cb7-19">        shape <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Penguin species"</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidyverse-python-ports/index_files/figure-html/cell-4-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Folks have <a href="https://datascienceworkshops.com/blog/heuristics-for-translating-ggplot2-to-plotnine/">heuristics</a> to translate ggplot2 code to plotnine. These help understand the nuances between the two.</p>
</section>
<section id="pyjanitor" class="level2">
<h2 class="anchored" data-anchor-id="pyjanitor">pyjanitor</h2>
<p>OK, this one is cheating a bit because the <a href="https://github.com/sfirke/janitor">janitor</a> package by <a href="https://twitter.com/samfirke">Sam Firke</a> is not part of the tidyverse. One more package that uses ‘tidyverse-like’ verbs is <a href="https://github.com/pyjanitor-devs/pyjanitor">pyjanitor</a>. With pyjanitor, you can clean column names, identify duplicate entries, and more.</p>
<div id="a4e36241" class="cell" data-message="false" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> janitor <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> clean_names</span>
<span id="cb8-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb8-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb8-4"></span>
<span id="cb8-5">example_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb8-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Terrible Name 1'</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name1'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name2'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name3'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name4'</span>],</span>
<span id="cb8-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'PascalCase'</span>: [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">150.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">200.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">300.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">400.0</span>],</span>
<span id="cb8-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'this_has_punctuation?'</span>: [np.nan, np.nan, np.nan, np.nan],</span>
<span id="cb8-9">}</span>
<span id="cb8-10"></span>
<span id="cb8-11">pd.DataFrame.from_dict(example_df).clean_names()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="9">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">terrible_name_1</th>
<th data-quarto-table-cell-role="th">pascalcase</th>
<th data-quarto-table-cell-role="th">this_has_punctuation_</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>name1</td>
<td>150.0</td>
<td>NaN</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>name2</td>
<td>200.0</td>
<td>NaN</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>name3</td>
<td>300.0</td>
<td>NaN</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>name4</td>
<td>400.0</td>
<td>NaN</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<p>Python’s pandas allows you to <a href="https://tomaugspurger.github.io/method-chaining.html">method chain</a> with <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.pipe.html">pipes</a>. They can be used with pyjanitor, as well.</p>
<div id="fc5be98b" class="cell" data-message="false" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> janitor <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> clean_names, remove_empty</span>
<span id="cb9-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb9-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb9-4"></span>
<span id="cb9-5">example_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb9-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Terrible Name 1'</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name1'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name2'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name3'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name4'</span>],</span>
<span id="cb9-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'PascalCase'</span>: [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">150.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">200.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">300.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">400.0</span>],</span>
<span id="cb9-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'this_has_punctuation?'</span>: [np.nan, np.nan, np.nan, np.nan],</span>
<span id="cb9-9">}</span>
<span id="cb9-10"></span>
<span id="cb9-11">(pd.DataFrame.from_dict(example_df)</span>
<span id="cb9-12">    .pipe(clean_names)</span>
<span id="cb9-13">    .pipe(remove_empty)</span>
<span id="cb9-14">)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="10">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">terrible_name_1</th>
<th data-quarto-table-cell-role="th">pascalcase</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>name1</td>
<td>150.0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>name2</td>
<td>200.0</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>name3</td>
<td>300.0</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>name4</td>
<td>400.0</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>While Python syntax and conventions are still on my “to-learn” list, it is helpful to know there are packages that can bring the familiarity of the tidyverse to Python.</p>
<section id="additional-resources" class="level3">
<h3 class="anchored" data-anchor-id="additional-resources">Additional resources</h3>
<p>I came across other packages that port the tidyverse to Python. I didn’t investigate them deeply but wanted to share in case they are helpful.</p>
<ul>
<li><a href="https://github.com/talegari/tidypandas">tidypandas</a></li>
<li><a href="https://github.com/has2k1/plydata">plydata</a></li>
<li><a href="https://github.com/markfairbanks/tidypolars">tidypolars</a></li>
<li><a href="https://github.com/pwwang/datar">datar</a></li>
</ul>
<p>If you recommend these packages or know of others, please let me know on Twitter!</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>2024-01-13 Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Adam Austin started a <a href="https://fosstodon.org/deck/@ataustin/111664896223556142">thread of dplyr-alike Python packages</a> on Mastodon.</p>
</div>
</div>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Working in Python but miss <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a>' tidyverse? 🐍 Here are three+ packages that port tidyverse-like syntax to use in your <a href="https://twitter.com/hashtag/pydata?src=hash&amp;ref_src=twsrc%5Etfw">#pydata</a> work.<br><br>Blog post: <a href="https://t.co/ScGycjYyOo">https://t.co/ScGycjYyOo</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1523810181854859265?ref_src=twsrc%5Etfw">May 9, 2022</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>
</section>

 ]]></description>
  <category>reference</category>
  <guid>https://ivelasq.rbind.io/blog/tidyverse-python-ports/</guid>
  <pubDate>Mon, 09 May 2022 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/tidyverse-python-ports/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Understanding the native R pipe |&gt;</title>
  <link>https://ivelasq.rbind.io/blog/understanding-the-r-pipe/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/understanding-the-r-pipe/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Blue and yellow dots making up the night sky"></p>
<figcaption>Henri-Edmond Cross, Landscape with Stars, (1905–1908)</figcaption>
</figure>
</div>
<p>A while back, I wrote <a href="https://mobile.twitter.com/ivelasq3/status/1404947187155574787">this tweet</a> showing many (not all!) of the ways one might search for a particular set of columns in a data frame using R. Several of these approaches used the {magrittr} pipe (<code>%&gt;%</code>) and the native R pipe (<code>|&gt;</code>), the latter of which has been available since R version 4.1.0. The {magrittr} and native R pipes work in different ways and one’s mental model of each requires some maintenance. This is the story of how I learned to understand the native R pipe.</p>
<section id="how-laziness-sparked-this-post" class="level2">
<h2 class="anchored" data-anchor-id="how-laziness-sparked-this-post">How laziness sparked this post</h2>
<p>When I am feeling lazy, I use base R for quick plots:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" 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;">plot</span>(mtcars<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, mtcars<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg)</span></code></pre></div></div>
<p>Because that clearly saves a lot of time compared to the {ggplot2} alternative 😄:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" 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;">library</span>(ggplot2)</span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(magrittr)</span>
<span id="cb2-3"></span>
<span id="cb2-4">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb2-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;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> hp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> mpg)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb2-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>()</span></code></pre></div></div>
<p>One day, I was feeling <em>extra</em> lazy, so I tried using the new native R pipe <code>|&gt;</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(hp, mpg)</span>
<span id="cb3-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; Error in get(as.character(FUN), mode = "function", envir = envir) :</span></span>
<span id="cb3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; object 'mpg' of mode 'function' was not found</span></span></code></pre></div></div>
<p>Oh no! Why an error?</p>
<p>It was a complete misunderstanding of the native R pipe. I thought piping the data with the native R pipe would replace the need for the <code>data$column</code> notation. Turns out, that is not what the native R pipe does at all. So, this attempt to be lazy culminated in an adventu<strong>R</strong>e to figure out why that doesn’t work and what works instead.</p>
</section>
<section id="how-the-magrittr-pipe-works" class="level2">
<h2 class="anchored" data-anchor-id="how-the-magrittr-pipe-works">How the {magrittr} pipe <code>%&gt;%</code> works</h2>
<p>First, let’s examine the pipe that you might be more familiar with (if you use the {tidyverse} dialect): the <code>%&gt;%</code> forward pipe from the {magrittr} package.</p>
<p>Without any dot syntax (<code>.</code>), the {magrittr} pipe <code>%&gt;%</code> is an <a href="https://en.wikipedia.org/wiki/Infix_notation">infix operator</a> that pipes (moves) what is written on the left-hand side (LHS) of the pipe into the first argument of the function on the right-hand side (RHS) of the pipe. Since R is prone to expressions with many nested parentheses, piping allows one to reason about code from left to right (as when writing in English), instead of right to left with many nested parentheses (see example below).</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Before I learned case_when() 👀 <a href="https://t.co/khJpueqob2">pic.twitter.com/khJpueqob2</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1466915834002128901?ref_src=twsrc%5Etfw">December 3, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
<p>From the {magrittr} documentation, the pipe’s usage is thus: <code>LHS %&gt;% RHS</code>. It might be easier to think of a ‘pipe’ as one of the famous ‘warp pipes’ from Super Mario Bros.&nbsp;— it warps Mario from the LHS into the first argument of the RHS function!</p>
<center>
<img src="https://ivelasq.rbind.io/blog/understanding-the-r-pipe/mario.gif" class="img-fluid" alt="GIF of Mario game where Mario is bouncing in and out of two pipes">
</center>
<p>So:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">mtcars2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb4-2">  mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb4-3">  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;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hi_mpg =</span> 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;">if_else</span>(mpg <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;">25</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"high"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"low"</span>))</span></code></pre></div></div>
<p>Is equivalent to:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">mtcars2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb5-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;">mutate</span>(mtcars, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hi_mpg =</span> 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;">if_else</span>(mpg <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;">25</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"high"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"low"</span>))</span></code></pre></div></div>
<p>And,</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(hp, mpg)</span></code></pre></div></div>
<p>Is equivalent to:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(mtcars, hp, mpg)</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># or, more explicitly</span></span>
<span id="cb7-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> mtcars, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> hp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> mpg)</span></code></pre></div></div>
<p>Which does not work and gives us an error message, because the first two arguments of <code>plot()</code> should be objects for the x and y axes (<code>mtcars</code> is an odd x-axis but technically works), and the third argument is for the type of plot (<code>mpg</code> definitely doesn’t work there).</p>
<p>If you want the LHS to be passed somewhere other than the first argument with the {magrittr} pipe, you can use its dot syntax (<code>.</code>): <code>y %&gt;% f(x, .)</code> is equivalent to <code>f(x, y)</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb8-2">  <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> hp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> .)</span></code></pre></div></div>
<p>Is equivalent to:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lm</span>(mpg <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></code></pre></div></div>
<p>So, how do we get the {magrittr} pipe to work with <code>plot()</code>? We can use the dot syntax as a placeholder for the data frame. However, this also does not work:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(.<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, .<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg)</span>
<span id="cb10-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; Error in match.fun(panel) :</span></span>
<span id="cb10-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; '.$mpg' is not a function, character or symbol</span></span></code></pre></div></div>
<p>Why? The error gives a hint that something is wrong with the <code>.$mpg</code> step.<sup>1</sup> By default, the {magrittr} pipe passes the LHS into the first argument of the RHS, so the call giving the error above is equivalent to writing:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(mtcars, mtcars<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, mtcars<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg)</span>
<span id="cb11-2"></span>
<span id="cb11-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># or, more explicitly</span></span>
<span id="cb11-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> mtcars, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> mtcars<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;">type =</span> mtcars<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg)</span></code></pre></div></div>
<p>Which does not work nor is what we intended (we want to have <code>mtcars$hp</code> on the x-axis, and <code>mtcars$mpg</code> on the y-axis). The way to get the {magrittr} pipe to do what we want with <code>plot()</code> is to use its curly brace <code>{}</code> syntax. By wrapping the RHS in curly braces, we can override the rule where the LHS is passed to the first argument:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> {<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(.<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, .<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg)}</span></code></pre></div></div>
<p>This works! It’s equivalent to having written:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(mtcars<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, mtcars<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg)</span></code></pre></div></div>
<p>OK! Now, we can apply what we’ve learned to the native R pipe. Right? …Right?</p>
<center>
<img src="https://ivelasq.rbind.io/blog/understanding-the-r-pipe/padme.jpg" class="img-fluid" alt="Meme of Anakin and Padme with Anakin saying he understands the magrittr pipe, Padme asking if that means he understands the native pipe, and Anakin’s smirk implying that nope">
</center>
</section>
<section id="actually-i-think-we-need-a-detour-to-explain-anonymous-lambda-functions-before-we-can-explain-how-works" class="level2">
<h2 class="anchored" data-anchor-id="actually-i-think-we-need-a-detour-to-explain-anonymous-lambda-functions-before-we-can-explain-how-works">ACTUALLY I THINK WE NEED A DETOUR TO EXPLAIN ANONYMOUS (LAMBDA) FUNCTIONS BEFORE WE CAN EXPLAIN HOW <code>|&gt;</code> WORKS</h2>
<p>Why anonymous? Because they are not named functions from a package or written by you and stored in a function object. Anonymous functions are created on-the-fly, applied immediately, and don’t persist after they’ve been used: <code>function(x) {}</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) {</span>
<span id="cb14-2">  x[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.max</span>(x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg), ]</span>
<span id="cb14-3">}</span></code></pre></div></div>
<p>What does this do? It creates an anonymous function (also known as a lambda function) if it is not saved to an object.</p>
<p>Introduced in R 4.1, the shortcut for anonymous functions <code>\(x) {}</code> is the same as <code>function(x) {}</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># equivalent to the above</span></span>
<span id="cb15-2">\(x) {</span>
<span id="cb15-3">  x[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.max</span>(x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg), ]</span>
<span id="cb15-4">}</span></code></pre></div></div>
<p>What you gain from writing an anonymous function is that you get to direct traffic by explicitly stating the inputs and how they will be used in the function. Going back to our discussion of pipes, you get to direct exactly where the LHS of the pipe goes in the RHS.</p>
</section>
<section id="how-the-native-r-pipe-works" class="level2">
<h2 class="anchored" data-anchor-id="how-the-native-r-pipe-works">How the native R pipe works</h2>
<p>Like the {magrittr} pipe <code>%&gt;%</code>, the native R pipe <code>|&gt;</code> pipes the LHS into the first argument of the function on the RHS: <code>LHS |&gt; RHS</code>.</p>
<p>You can write:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>()</span></code></pre></div></div>
<p>Which is equivalent to:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(mtcars))</span></code></pre></div></div>
<div class="callout callout-style-default callout-warning callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Warning</span>An important note
</div>
</div>
<div class="callout-body-container callout-body">
<p>On the RHS of <code>|&gt;</code>, you need to include the function as a function call, which means appending an <code>()</code> at the end of the function name, rather than just its name. For example, the square root function is called by writing <code>sqrt()</code>. If you try to run <code>mtcars |&gt; sqrt</code> without the <code>()</code> at the end, you will get an error: <code>Error: The pipe operator requires a function call as RHS</code>.</p>
</div>
</div>
<p>So, the native R pipe pipes the LHS into the first argument of the function on the RHS (with an extra requirement of needing a function call on the RHS). <strong>But that’s all!</strong> If you want to do anything <em>beyond</em> piping the LHS into the first argument of the RHS function, then you need the special anonymous function syntax introduced above.</p>
<p>A gotcha here is that we also needed to write parentheses around the anonymous function, such that a pseudocode version of the above is <code>mtcars |&gt; (anonymous-function-definition)()</code>. The reason for this is so that the second set of <code>()</code> properly points to the complex expression inside the first set of <code>()</code> as the function being called.<sup>2</sup><sup>3</sup></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> (\(x) {</span>
<span id="cb18-2">   x[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.max</span>(x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg), ]</span>
<span id="cb18-3">})()</span></code></pre></div></div>
<p>Thinking back to what we learned about the {magrittr} pipe <code>%&gt;%</code>, you might be tempted to use the dot syntax (<code>.</code>). A final important note is that the dot syntax does not work with the native R pipe <code>|&gt;</code> since the dot syntax is a feature of {magrittr} and not of base R. For example, this works:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(.<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp)</span></code></pre></div></div>
<p>But this doesn’t because there is no support for the dot syntax with the native R pipe:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb20-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(.<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp)</span>
<span id="cb20-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#&gt; Error in pairs.default(data.matrix(x), ...) : object '.' not found</span></span></code></pre></div></div>
<p>However, if you create an anonymous function, you can decide what the input argument names are, whether <code>.</code>, <code>x</code>, <code>data</code>, anything! So, if you are tied to the dot syntax in {magrittr}, you can ‘bootstrap’ your own dot syntax with <code>\(.) {}</code>.</p>
<p>In sum, the native R pipe does not support the dot syntax unless you explicitly define your own.</p>
</section>
<section id="getting-to-the-solution" class="level2">
<h2 class="anchored" data-anchor-id="getting-to-the-solution">Getting to the solution</h2>
<p>Finally, we get to the solution: to get the native R pipe to do what we wanted to do with <code>plot()</code>, we need to use an anonymous function and bootstrap the dot syntax (or any other argument name) for ourselves:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># verbosely</span></span>
<span id="cb21-2">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> (<span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(.) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(.<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, .<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg))()</span>
<span id="cb21-3"></span>
<span id="cb21-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># using the anonymous function shortcut, emulating the dot syntax</span></span>
<span id="cb21-5">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> (\(.) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(.<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, .<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg))()</span>
<span id="cb21-6"></span>
<span id="cb21-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># or if you prefer x to .</span></span>
<span id="cb21-8">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> (\(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg))()</span>
<span id="cb21-9"></span>
<span id="cb21-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># or if you prefer to be explicit with argument names</span></span>
<span id="cb21-11">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> (\(data) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hp, data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mpg))()</span></code></pre></div></div>
<p>That’s it! 🎉 It can be done, but the initial attempt to be lazy ended up taking much more time than originally expected. As the saying goes, ‘a pipe in time saves nine.’</p>
<center>
<img src="https://ivelasq.rbind.io/blog/understanding-the-r-pipe/mario2.gif" class="img-fluid" alt="GIF of Mario running across pipes avoiding piranha plants">
</center>
<div class="callout callout-style-default callout-warning callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Warning</span>2022-03-31 Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>While this post is meant to be an exploration of the new native R pipe to understand how it works, a few folks have shared another solution: <code>mtcars |&gt; with(plot(hp, mpg))</code>. This is an (admittedly simpler!) alternative to <code>mtcars |&gt; (\(data) plot(data$hp, data$mpg))()</code>.</p>
<p>Following what we have learned so far:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">with</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(hp, mpg))</span></code></pre></div></div>
<p>Is equivalent to:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb23-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">with</span>(mtcars, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(hp, mpg))</span></code></pre></div></div>
<p>Since it passes <code>mtcars</code> to the first argument on the RHS. This also creates the original plot we wanted, <code>plot(mtcars$hp, mtcars$mpg)</code>.</p>
</div>
</div>
</section>
<section id="the-true-lazy-way" class="level2">
<h2 class="anchored" data-anchor-id="the-true-lazy-way">The true lazy way</h2>
<p>This was an exploration of how the <code>%&gt;%</code> and <code>|&gt;</code> pipes work, but we also have another option! The {magrittr} <strong>exposition pipe</strong> <code>%$%</code> ‘exposes’ the names in the LHS to the RHS expression.</p>
<p>So, the winner for lazy {magrittr} users like myself is:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb24-1">mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%$%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(hp, mpg)</span></code></pre></div></div>
<p>No dot syntax, no curly braces, no anonymous functions, no terminal function call, just a pipe and column names! It effectively emulates how <code>plot()</code> would work if it were a {tidyverse} function.</p>
<p>Really though, all pipe users are winners here! As shown in the alignment chart tweet, we have many options of doing what we want to do with R.</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
I couldn't resist getting in on the fun, updated for R &gt;= 4.1, created using {gt}! h/t <a href="https://twitter.com/skyetetra?ref_src=twsrc%5Etfw"><span class="citation" data-cites="skyetetra">@skyetetra</span></a> <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> <a href="https://twitter.com/hashtag/tidyverse?src=hash&amp;ref_src=twsrc%5Etfw">#tidyverse</a> <a href="https://twitter.com/hashtag/magrittr?src=hash&amp;ref_src=twsrc%5Etfw">#magrittr</a> <a href="https://twitter.com/hashtag/alignmentchart?src=hash&amp;ref_src=twsrc%5Etfw">#alignmentchart</a> <br><br>Repo here: <a href="https://t.co/gjGWLKYYG5">https://t.co/gjGWLKYYG5</a> <a href="https://t.co/1Ez6eQKkGd">pic.twitter.com/1Ez6eQKkGd</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1404947187155574787?ref_src=twsrc%5Etfw">June 15, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
</section>
<section id="more-resources" class="level2">
<h2 class="anchored" data-anchor-id="more-resources">More resources</h2>
<ul>
<li><a href="https://magrittr.tidyverse.org/reference/pipe.html">{magrittr} forward pipe operator help documentation</a> (or <code>?"%&gt;%"</code> in your R console)</li>
<li><a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/pipeOp.html">Forward pipe operator help documentation</a> (or <code>?pipeOp</code> in your R console)</li>
<li><a href="https://adv-r.hadley.nz/functions.html">Functions chapter in Advanced R</a></li>
</ul>
</section>
<section id="extra-credit-for-those-who-made-it-this-far" class="level2">
<h2 class="anchored" data-anchor-id="extra-credit-for-those-who-made-it-this-far">Extra credit for those who made it this far</h2>
<p>How would you do this with the proposed native R pipe-bind <code>=&gt;</code> syntax? Respond to my <a href="https://twitter.com/ivelasq3">tweet</a> about this blog post once you have the answer!</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
New blog post 👩🏻‍💻📝 Understanding the native R pipe |&gt;<br><br>In this post, I attempted the native R <a href="https://twitter.com/hashtag/pipeoperator?src=hash&amp;ref_src=twsrc%5Etfw">#pipeoperator</a> and was warped into the RHS, and emerged from my misadventuRe having learned all about the <a href="https://twitter.com/hashtag/magrittr?src=hash&amp;ref_src=twsrc%5Etfw">#magrittr</a> and <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> pipes.<br><br>Post: <a href="https://t.co/VOC1C6WGvl">https://t.co/VOC1C6WGvl</a> <a href="https://t.co/IDAHvwyE4K">pic.twitter.com/IDAHvwyE4K</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1483554890152439811?ref_src=twsrc%5Etfw">January 18, 2022</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
</section>
<section id="acknowledgements" class="level2">
<h2 class="anchored" data-anchor-id="acknowledgements">Acknowledgements</h2>
<p>The author thanks <a href="https://github.com/gvelasq"><span class="citation" data-cites="gvelasq">@gvelasq</span></a> for his comments on the first draft of this blog post, and all who replied to the <a href="https://twitter.com/ivelasq3/status/1483554890152439811">Twitter thread</a> with insights, alternatives, and feedback.</p>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>Running the same line without that argument, <code>mtcars %&gt;% plot(.$hp)</code>, does run without an error (but is not the plot that we want since it is using <code>mtcars</code> as the first argument, as mentioned above).↩︎</p></li>
<li id="fn2"><p>Curly braces for the first expression, <code>{}()</code>, work too: <code>mtcars |&gt; {\(x) {x[which.max(x$mpg),]}}()</code>. See Ronak Shah’s reply in this <a href="https://stackoverflow.com/questions/67633022/what-are-the-differences-between-rs-new-native-pipe-and-the-magrittr-pipe/67638063#67638063">StackOverflow thread</a> for an example.↩︎</p></li>
<li id="fn3"><p>Or for more on this, see Q2 and its answer in the ‘Functions’ chapter of <a href="https://advanced-r-solutions.rbind.io/functions.html">Advanced R Solutions</a>.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>explanation</category>
  <guid>https://ivelasq.rbind.io/blog/understanding-the-r-pipe/</guid>
  <pubDate>Tue, 18 Jan 2022 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/understanding-the-r-pipe/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Creating a dataset from an image using reticulate in R Markdown</title>
  <link>https://ivelasq.rbind.io/blog/reticulate-data-recreation/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/reticulate-data-recreation/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Jungle with green trees and a red sun"></p>
<figcaption>Henri Rousseau, Virgin Forest with Sunset (1910)</figcaption>
</figure>
</div>
<p>Last week, a paper started making the Twitter rounds. <a href="https://www.biorxiv.org/content/10.1101/2020.07.30.228916v1.full.pdf">Selective attention in hypothesis-driven data analysis</a> by Professors Itai Yanai and Martin Lerche looked into whether providing specific hypotheses prevented students from fully exploring a dataset. The authors artificially created a dataset that, when plotted, clearly showed the outline of a cartoon gorilla.</p>
<center>
<img src="https://ivelasq.rbind.io/blog/reticulate-data-recreation/main.png" class="img-fluid" alt="Cartoon gorilla and its recreation in ggplot2">
</center>
<p>I will leave you to read the paper to find out the results but something that interested me was the dataset created from the image. The authors mentioned that they used a Python function called ‘getpixel’, manipulated the dataset into groups, and plotted it in {ggplot2}. I am learning the <a href="https://rstudio.github.io/reticulate/">{reticulate}</a> package which allows R to interface with Python and thought this would be a fun exercise to try.</p>
<p>With that, let’s recreate this dataset entirely within R Markdown! In addition to being able to copy/paste the code below, I have also provided it as a project on <a href="https://rstudio.cloud/project/2949291">RStudio Cloud</a> if you’d like to run the whole thing at once.</p>
<section id="install-packages" class="level2">
<h2 class="anchored" data-anchor-id="install-packages">Install packages</h2>
<p>First up is installing the R packages:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb1-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb1-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Install packages if not already installed</span></span>
<span id="cb1-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages(c("tidyverse", "reticulate"))</span></span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(reticulate)</span>
<span id="cb1-6"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
<p>In your project, create a folder called “image”. Save the image you would like to convert to a dataset in that folder. To recreate this paper’s dataset, go to <a href="https://classroomclipart.com/clipart-view/Clipart/Black_and_White_Clipart/Animals/gorilla-waving-cartoon-black-white-outline-clipart-914_jpg.htm">this</a> page and download the cartoon gorilla.</p>
<p>The paper mentions the ‘getpixel’ function. With a bit of digging, we find that is from the package <code>pillow</code> (a fork from a package called <code>PIL</code>). Like in R, we need to install the package. In an R Markdown document, I run the functions from {reticulate} below.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb2-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">use_python</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/usr/local/bin/python"</span>)</span>
<span id="cb2-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># If you haven't installed Python, the line below will prompt you!</span></span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_install</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pillow"</span>)</span>
<span id="cb2-5"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
<p>Since {reticulate} is the package that allows you to call Python, if you do not have Python installed, then you will get a message (which you would reply Y to):</p>
<pre><code>No non-system installation of Python could be found.
Would you like to download and install Miniconda?
Miniconda is an open source environment management system for Python.
See https://docs.conda.io/en/latest/miniconda.html for more details.</code></pre>
</section>
<section id="create-coordinates" class="level2">
<h2 class="anchored" data-anchor-id="create-coordinates">Create coordinates</h2>
<p><a href="https://stackoverflow.com/questions/58398300/find-all-coordinates-of-black-grey-pixels-in-image-using-python">This</a> Stack Overflow thread was very helpful to determine what we need to do with the ‘getpixel’ function in <code>pillow</code>. Again, like in R, we need to call the functions we need but this time, we are doing it in a <code>python</code> chunk.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb4-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{python}</span></span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb4-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> PIL <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Image</span>
<span id="cb4-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
<p>Then, we point to the image and create coordinates pixels for the outline of the cartoon. We can set a threshold level for which pixels to keep/discard.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb5-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{python}</span></span>
<span id="cb5-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Thanks to Bart Huntley for pointing out a typo previously in this chunk!</span></span>
<span id="cb5-3">im <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Image.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/cloud/project/image/gorilla.jpg"</span>)</span>
<span id="cb5-4">pixels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.asarray(im)</span>
<span id="cb5-5"></span>
<span id="cb5-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Set threshold level</span></span>
<span id="cb5-7">threshold_level <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span></span>
<span id="cb5-8"></span>
<span id="cb5-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Find coordinates of all pixels below threshold</span></span>
<span id="cb5-10">coords <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.column_stack(np.where(pixels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> threshold_level))</span>
<span id="cb5-11"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</section>
<section id="bring-back-into-r" class="level2">
<h2 class="anchored" data-anchor-id="bring-back-into-r">Bring back into R</h2>
<p>This results in a NumPy ndarray called <code>coords</code> that contains the coordinates of the pixels of the outline. That’s great but… it’s in Python! How do we bring it back into R?</p>
<p>The <a href="https://ugoproto.github.io/ugo_r_doc/pdf/reticulate.pdf">{reticulate} Cheat Sheet</a> was very helpful in figuring this out. The section “Python in R Markdown” shows that you can use the <code>py</code> object to access objects created in Python chunks from R chunks.</p>
<center>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/reticulate-data-recreation/Screen Shot 2021-09-27 at 11.40.55 PM.png" class="img-fluid figure-img" alt="Python in R Markdown cheat sheet"></p>
<figcaption>Python Cheatsheet</figcaption>
</figure>
</div>
</center>

<p>Knowing that, we can create an R object from coords using <code>py</code>. Next, we follow the steps outlined in the paper for the data preparation.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb6-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb6-2">coords <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb6-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>coords) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample_n</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1768</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bmi =</span> V2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">17</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;">15</span>,</span>
<span id="cb6-6">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">steps =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15000</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> V1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15000</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;">max</span>(V1)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">randvar =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</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;">0</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="cb6-8">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">randi =</span> steps <span 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> randvar),</span>
<span id="cb6-9">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">gender =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">case_when</span>(randi <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(steps) <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;">"Female"</span>,</span>
<span id="cb6-10">                            <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Male"</span>))</span>
<span id="cb6-11"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
<p>If we’d like to see the distribution of data by male/female, we can use <code>count()</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb7-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb7-2">coords <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb7-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count</span>(gender)</span>
<span id="cb7-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</section>
<section id="create-plots" class="level2">
<h2 class="anchored" data-anchor-id="create-plots">Create plots</h2>
<p>Now for the fun part - visualizing the plots (spoiler: one should always do this before starting an analysis)!</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb8-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb8-2">coords <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb8-3">  <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;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> bmi,</span>
<span id="cb8-4">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> steps)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xlim</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;">15000</span>)</span>
<span id="cb8-8"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
<center>
<img src="https://ivelasq.rbind.io/blog/reticulate-data-recreation/index.png" class="img-fluid" alt="ggplot2 image of pixel cartoon gorilla">
</center>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb9-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb9-2">coords <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb9-3">  <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;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> bmi,</span>
<span id="cb9-4">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> steps,</span>
<span id="cb9-5">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> gender)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xlim</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;">15000</span>)</span>
<span id="cb9-9"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
<center>
<img src="https://ivelasq.rbind.io/blog/reticulate-data-recreation/index2.png" class="img-fluid" alt="ggplot2 image of pixel cartoon gorilla with random dots colored by gender">
</center>
<p>With that, we’ve seamlessly gone from Python to R and created a dataset leveraging the power of both languages. Thanks to Professors Yanai and Lerche for their publication!</p>
<center>
<em>Liked this post? I’d love for you to retweet!</em>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Did you see the paper where a dataset was created from a cartoon and thought, how do I create that using <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a>? This blog post walks through using reticulate to use <a href="https://twitter.com/hashtag/Python?src=hash&amp;ref_src=twsrc%5Etfw">#Python</a> and ggplot2 in the same R markdown notebook 😎🐍 <a href="https://t.co/4CbXzRd3PN">https://t.co/4CbXzRd3PN</a> <a href="https://t.co/Kq4WsaKHMk">pic.twitter.com/Kq4WsaKHMk</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1443216191858769922?ref_src=twsrc%5Etfw">September 29, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/reticulate-data-recreation/</guid>
  <pubDate>Tue, 28 Sep 2021 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/reticulate-data-recreation/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Why I’m excited to join RStudio, told through a blogdown metadata project</title>
  <link>https://ivelasq.rbind.io/blog/why-rstudio/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/why-rstudio/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Olive trees against a blue background  and a bright sun"></p>
<figcaption>Vincent van Gogh, The Olive Trees (1889)</figcaption>
</figure>
</div>
<p>I am excited to announce that I’ve joined the RStudio Marketing team! I will be creating content on the <a href="https://blog.rstudio.com/">RStudio Blog</a> that will announce news and share stories from the company, users, and partners. I just started this week and, ready to jump in, I decided that I’d like to deep dive into previous blog posts.</p>
<p>The RStudio blog is written using <a href="https://bookdown.org/yihui/blogdown/">blogdown</a> and each blog entry contains metadata in the YAML header. Since there are hundreds of blog entries, I decided to use R to quickly pull all this information into an analyzable data frame. While figuring out how to do this, I was reminded of why I am so excited to join RStudio in the first place (and if you want to jump straight into the code, click here!)</p>
<section id="the-awesomeness-that-is-the-r-community" class="level2">
<h2 class="anchored" data-anchor-id="the-awesomeness-that-is-the-r-community">The awesomeness that is the R community</h2>
<p>As I started the task of pulling the YAML information, I remembered a blogpost from <a href="https://twitter.com/grrrck">Garrick Aden-Buie</a> called <a href="https://www.garrickadenbuie.com/blog/find-blogdown-tags/">Find, count and list tags in all blogdown posts</a> (thanks, Garrick!). The post taught me about <code>blogdown:::scan_yaml()</code> which was exactly what I needed to get the information from all the YAML headers in the files.</p>
<p>The members of the R Community, including others at RStudio, are incredibly collaborative and helpful, and I hope to be able to contribute to others’ learning as well.</p>
</section>
<section id="rstudio-tools-rock" class="level2">
<h2 class="anchored" data-anchor-id="rstudio-tools-rock">RStudio tools rock</h2>
<p>I remember when my older brother introduced me to the tidyverse in graduate school after I had been struggling to understand how to program in R. I was amazed by its usability and functionality and it enabled me to learn more, learn quicker, and learn better. I’ve been fortunate enough to use RStudio tools for my work, like <a href="https://shiny.rstudio.com/">Shiny</a> and <a href="https://www.shinyapps.io/">shinyapps.io</a>, and each time appreciated the thoughtful and deep work that RStudio does with its services and products.</p>
<p>How great is it that the blogdown team anticipated the need to look at a blog’s metadata and already created a function that scans the YAML?! And that we can create a blog using R? And doing so is excellently <a href="https://bookdown.org/yihui/blogdown/">documented</a>?</p>
<p>In addition, below you will see many different <a href="https://www.tidyverse.org/">tidyverse</a> packages (dplyr, here, tibble, tidyr) being used as well. The seamless integration of R packages, tools, and services makes projects like this one possible and easy.</p>
</section>
<section id="so-much-to-write-about" class="level2">
<h2 class="anchored" data-anchor-id="so-much-to-write-about">So much to write about</h2>
<p>If you check out the <a href="https://blog.rstudio.com/tags/">tags</a> from the RStudio blog, you will see so many topics. APIs! BI tools! Package development! Interoperability! RStudio is working on so many things, open source and enterprise, and it is thrilling to be part of an organization that advocates for <a href="https://blog.rstudio.com/2021/05/12/code-first-data-science-for-the-enterprise2/">code-first</a> development, thrives in a diverse and supportive community, and thinks creatively about what challenges to tackle next.</p>
</section>
<section id="a-new-chapter-in-my-rstudio-journey" class="level2">
<h2 class="anchored" data-anchor-id="a-new-chapter-in-my-rstudio-journey">A new chapter in my RStudio journey</h2>
<p>I am proud to join an organization that I’ve long admired and hope that my contributions in this realm of RStudio’s business will promote the uptake of amazing RStudio products, and the crucial work RStudio does in free open-source software, data science education, and other spaces as a Public Benefit Corporation. I look forward to working alongside my colleagues at RStudio to achieve the company’s vision.</p>
<p>And with that… I give you, the code!</p>
</section>
<section id="the-code" class="level2">
<h2 class="anchored" data-anchor-id="the-code">The code</h2>
<section id="pulling-yaml-metadata-for-each-blog-post" class="level3">
<h3 class="anchored" data-anchor-id="pulling-yaml-metadata-for-each-blog-post">Pulling YAML metadata for each blog post</h3>
<p>I intended to create a data frame from a blogdown where every row represents a blog entry, and where we will have columns for (1) its title, (2), its author(s), (3) associated tags, and (4) associated categories. If you are using this code on your blogdown, you can change them to whichever YAML fields you would like.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load libraries</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Find the folder with the blog posts</span></span>
<span id="cb1-5">blogdown_content_path <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> here<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">here</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"post"</span>)</span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Scan yaml of all posts (make sure the blogdown project is open)</span></span>
<span id="cb1-8">meta_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb1-9">  blogdown<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scan_yaml</span>(blogdown_content_path)</span>
<span id="cb1-10"></span>
<span id="cb1-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create a data frame that pulls out the title, date, categories, and tags for each entry</span></span>
<span id="cb1-12">meta_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb1-13">  <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;">map_chr</span>(meta_list, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>),</span>
<span id="cb1-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">date =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(meta_list, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"date"</span>),</span>
<span id="cb1-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">categories =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(meta_list, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"categories"</span>),</span>
<span id="cb1-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tags =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(meta_list, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tags"</span>))</span></code></pre></div></div>
<p>In this case, there are entries where there is a vector within categories or tags - this is because a single blog post can have multiple categories or tags (see example <a href="https://blog.rstudio.com/2021/08/30/rstudio-connect-2021-08-custom-branding/">here</a>, which has “rstudio connect” and “featured” as categories).</p>
<center>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/why-rstudio/cells.png" class="img-fluid figure-img" alt="Cell names"></p>
<figcaption>Cell names</figcaption>
</figure>
</div>
</center>
<p>The following code separates the tags or categories with multiple values so that each value has its own column using a <code>pivot_longer()</code> followed by <code>unnest()</code>, then re-pivots the table to wide format using <code>pivot_wider()</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">meta_df_clean <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb2-2">  meta_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb2-3">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Put the fields with multiple options into one column called variable</span></span>
<span id="cb2-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_longer</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cols =</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;">"categories"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tags"</span>),</span>
<span id="cb2-5">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"variable"</span>,</span>
<span id="cb2-6">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb2-7">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Split out the fields with multiple options into individual rows</span></span>
<span id="cb2-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unnest</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cols =</span> value) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb2-9">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># For each blog entry, give each category or tag a number</span></span>
<span id="cb2-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(title, variable) <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;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">row_number</span>()) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb2-12">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pivot back to wide format</span></span>
<span id="cb2-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_wider</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_from =</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;">"id"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"variable"</span>),</span>
<span id="cb2-14">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_glue =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{variable}_{id}"</span>,</span>
<span id="cb2-15">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_from =</span> value)</span></code></pre></div></div>
<p>And that’s it! Now we have a data frame with each row denoting a blog entry, with its associated metadata.</p>
<p>Thank you so much for reading this article and I look forward to seeing you on the <a href="https://blog.rstudio.com">RStudio blog</a> or <a href="https://twitter.com/ivelasq3">Twitter</a>.</p>
<center>
<em>Liked this post? I’d love for you to retweet!</em>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Here's how to pull the YAML for your blogdown posts using <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a>; figuring out how to do this was a great example of why I am excited to join RStudio 🥳<br><br>blogpost with code: <a href="https://t.co/RdI4zEwfX8">https://t.co/RdI4zEwfX8</a><br>h/t to <a href="https://twitter.com/grrrck?ref_src=twsrc%5Etfw"><span class="citation" data-cites="grrrck">@grrrck</span></a> 's post on finding tags in blogdown: <a href="https://t.co/p85frQbAiG">https://t.co/p85frQbAiG</a> <a href="https://t.co/bWwH2rsIYf">pic.twitter.com/bWwH2rsIYf</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1437402771947458565?ref_src=twsrc%5Etfw">September 13, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>
</section>

 ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/why-rstudio/</guid>
  <pubDate>Mon, 13 Sep 2021 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/why-rstudio/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Politely scraping Wikipedia tables</title>
  <link>https://ivelasq.rbind.io/blog/politely-scraping/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/politely-scraping/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Bunches of purple violets with a white background"></p>
<figcaption>Pauline Powell Williams, Violets (1890)</figcaption>
</figure>
</div>
<p><a href="https://en.wikipedia.org/wiki/Main_Page">Wikipedia</a> is such an amazing website, and also a fantastic source of data for analysis projects. I often find myself <a href="https://en.wikipedia.org/wiki/Web_scraping">scraping</a> Wikipedia’s tables for information and then cleaning and using the data for whatever I am working on.</p>
<p>However, scraping a website can create issues if not done properly. Though not required, I like to use the <a href="https://github.com/dmi3kno/polite">{polite} package</a> to introduce myself to the website and ask for permission to scrape.</p>
<p>Recently, I submitted the <a href="https://en.wikipedia.org/wiki/List_of_national_independence_days#List">Wikipedia table on independence days around the world</a> to <a href="https://github.com/rfordatascience/tidytuesday">TidyTuesday</a> - resulting in many beautiful and creative visualizations from the R Community! This post walks through how to “politely” scrape the table and pull it into a flat data frame so that it’s ready for use.</p>
<section id="load-packages" class="level2">
<h2 class="anchored" data-anchor-id="load-packages">Load packages</h2>
<p>There are several packages needed for this walkthrough:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># To clean data</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(lubridate)</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(janitor)</span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># To scrape data</span></span>
<span id="cb1-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(rvest)</span>
<span id="cb1-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(httr)</span>
<span id="cb1-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(polite)</span></code></pre></div></div>
</section>
<section id="scrape-table" class="level2">
<h2 class="anchored" data-anchor-id="scrape-table">Scrape table</h2>
<p>First, we save the web page with the table that we would like as <code>url</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">url <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://en.wikipedia.org/wiki/List_of_national_independence_days"</span></span></code></pre></div></div>
<p>Next, we use <code>polite::bow()</code> to introduce ourselves to the host, Wikipedia. This reads the rules from <code>robots.txt</code> and makes sure we follow them. The object (<code>url_bow</code> in this case) is saved as an object of class <code>polite</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">url_bow <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> polite<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bow</span>(url)</span>
<span id="cb3-2">url_bow</span></code></pre></div></div>
<p>Next, we actually ‘scrape’ (pull the content of) the web page using <code>polite::scrape()</code>. This needs an object of class <code>polite</code> (created with <code>bow()</code> from before).</p>
<p>Since we politely scraped the entire web page, we want to use {rvest} to specify what exact content we’d like to pull out. We can do this using <code>html_nodes()</code>.</p>
<p>How do we know which node we want? There are probably other ways of doing this. As a Firefox and Mac user, I click Cmd + Shift + C which opens up the Developer Tools so that I can select a specific element from the web page. I hover over the table to determine what the HTML is called, in this case, <code>table.wikitable</code>.</p>
<center>
<img src="https://ivelasq.rbind.io/blog/politely-scraping/webpage.png" class="img-fluid" alt="Screenshot of Google's Inspector tool on Wikipedia">
</center>
<p>This object is saved as an HTML table which is great, but a data frame would be preferable for analysis. So the final step is to use <code>rvest::html_table()</code> to read this table as something with which we can use tidyverse tools. The parameter <code>fill = TRUE</code> allows you to fill empty rows with <code>NA</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">ind_html <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb4-2">  polite<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scrape</span>(url_bow) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># scrape web page</span></span>
<span id="cb4-3">  rvest<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">html_nodes</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"table.wikitable"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pull out specific table</span></span>
<span id="cb4-4">  rvest<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">html_table</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>) </span></code></pre></div></div>
</section>
<section id="flatten-table" class="level2">
<h2 class="anchored" data-anchor-id="flatten-table">Flatten table</h2>
<p>You will notice that <code>ind_html</code> is saved as a single object (a list) in which each element is a data frame. If we want to convert it to a flat data frame, we can specify that we want the content from only the first element <code>[[1]]</code>. We can then use <code>janitor::clean_names()</code> for nice, standardized column names.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">ind_tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb5-2">  ind_html[[<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;">%&gt;%</span> </span>
<span id="cb5-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clean_names</span>()</span></code></pre></div></div>
<p>That’s it! Now we’ve “politely” scraped the Wikipedia table into an analysis-ready data frame.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Additional steps to clean the file can be found in my <a href="https://github.com/ivelasq/data-visualization-portfolio/blob/main/independence-days/independence_days.R">GitHub repo</a>. After doing so, I submitted to #TidyTuesday by submitting an <a href="https://github.com/rfordatascience/tidytuesday/issues">issue</a> on their page. Then they approved and shared the dataset!</p>
<p>This was a very quick walkthrough. I recommend Ryo Nakagawara’s <a href="https://ryo-n7.github.io/2020-05-14-webscrape-soccer-data-with-R/">blog post on politely scraping websites</a>, especially if you would like (1) more in-depth explanations of what {polite} does and (2) more complex scraping examples.</p>
<p>Which Wikipedia table will you analyze next?</p>
<center>
<em>Liked this post? I’d love for you to retweet!</em>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
📢 A short blog post on how to "politely" scrape a Wikipedia table using <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a>. Which page will you scrape next?!<a href="https://t.co/cTIy8UIFKm">https://t.co/cTIy8UIFKm</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1420022159947096065?ref_src=twsrc%5Etfw">July 27, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/politely-scraping/</guid>
  <pubDate>Tue, 27 Jul 2021 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/politely-scraping/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Getting started in #rtistry</title>
  <link>https://ivelasq.rbind.io/blog/rtistry-intro/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Abstract pink flowers with red centers on a background of an orange spiral with brown background"></p>
<figcaption>E. A. Séguy, Vintage flower patterns (1925)</figcaption>
</figure>
</div>
<p>Artists in the R community have been using the <a href="https://twitter.com/hashtag/rtistry"><code>#rtistry</code></a> hashtag to demonstrate their gorgeous, dynamic art using only the R programming language. Their creations are amazing and they inspired me to try out generative art this dreary Sunday.</p>
<p>I am proud to showcase my first #rtistry plot ever! Kinda reminds me of <a href="https://www.reddit.com/r/nostalgia/comments/66s0hc/kid_pix/">KidPix</a> (remember KidPix?!). I wanted to share how I did it and welcome any feedback or advice, as this is totally new and I’m not even sure if I am doing it right?</p>
<center>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/rtistry2.png" class="img-fluid figure-img" alt="Generative art showing a repeated parametric equation"></p>
<figcaption>Final image</figcaption>
</figure>
</div>
</center>
<p><br> As always, we start with the packages we will use:</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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load packages</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(viridis)</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggdark)</span></code></pre></div></div>
</div>
<section id="write-a-parametric-equation" class="level2">
<h2 class="anchored" data-anchor-id="write-a-parametric-equation">Write a parametric equation</h2>
<p>First up is figuring out the function you will use to create the plot. I decided to go with a parametric equation for my first <code>#rtistry</code> plot. A parametric equation of a curve expresses the coordinates of points of the curve as functions of a variable. <a href="https://lifethroughamathematicianseyes.wordpress.com/2014/11/13/parametric-equations/">This blog post</a> explains the concept very clearly and also has various examples of wonderful parametric equations.</p>
<p>Why parametric equations? First, even simple equations can create beautiful symmetries. Second, they are easy to modify to find the <em>perfect</em> plot.</p>
<p>The simplest parametric equation uses cosine and sine to make the unit circle:</p>
<div class="cell" data-layout-align="center">
<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">circleFun <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;">center =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">diameter =</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;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>){</span>
<span id="cb2-2">    r <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> diameter <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb2-3">    tt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>pi,<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> npoints)</span>
<span id="cb2-4">    xx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> center[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> r <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(tt)</span>
<span id="cb2-5">    yy <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> center[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> r <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(tt)</span>
<span id="cb2-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</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;">x =</span> xx, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> yy))</span>
<span id="cb2-7">}</span>
<span id="cb2-8"></span>
<span id="cb2-9">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb2-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">circleFun</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><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;">2.3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)</span>
<span id="cb2-11"></span>
<span id="cb2-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dat,<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="cb2-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_path</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-2-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Circle plot" width="672"></p>
</figure>
</div>
</div>
</div>
<p>Let’s write a function to create a parametric equation. I based this equation on the aforementioned blog post equations. The parameters are:</p>
<ul>
<li>center: the center of the equation</li>
<li>npoints: the number of points used to evaluate the function.</li>
<li>c1, c2, c3, c4: the coefficients for the equation</li>
</ul>
<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">genFun <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;">center =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c1 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c2 =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c3 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.28</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c4 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.3</span>){</span>
<span id="cb3-2">    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</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>pi, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> npoints)</span>
<span id="cb3-3">    xx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> center[<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> c1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(c2<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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(c2<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;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(c3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>c4<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>t)))</span>
<span id="cb3-4">    yy <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> center[<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> c1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(c2<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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(c3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>c4<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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(c3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>c4<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>t))</span>
<span id="cb3-5">    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;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> xx, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> yy)</span>
<span id="cb3-6">    </span>
<span id="cb3-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(a)</span>
<span id="cb3-8">}</span></code></pre></div></div>
</div>
<p>Playing around with the function, we see how the graph gets smoother with more points and how the shape changes with different coefficients.</p>
<div class="cell" data-layout-align="center">
<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">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">genFun</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><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;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)</span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dat, <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="cb4-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_path</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-4-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Different shapes of a parametric equation" width="672"></p>
</figure>
</div>
</div>
</div>
<div class="cell" data-layout-align="center">
<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">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb5-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">genFun</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><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;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c1 =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c2 =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c3 =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c4 =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb5-3"></span>
<span id="cb5-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dat, <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="cb5-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_path</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-5-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Different shapes of a parametric equation" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="create-variation-within-the-graph" class="level2">
<h2 class="anchored" data-anchor-id="create-variation-within-the-graph">Create variation within the graph</h2>
<p>Now that we have a basic shape, let’s play around with different aspects of the graph:</p>
<ul>
<li>geoms</li>
<li>Aesthetic specifications</li>
<li>Repetition</li>
</ul>
<section id="geoms" class="level3">
<h3 class="anchored" data-anchor-id="geoms">geoms</h3>
<p>We started off with <code>geom_path</code> but can play around with other geoms too. Here it is with <code>geom_line</code>:</p>
<div class="cell" data-layout-align="center">
<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">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb6-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">genFun</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><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;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>)</span>
<span id="cb6-3"></span>
<span id="cb6-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dat, <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="cb6-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-6-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Parametric equation with an abstract look" width="672"></p>
</figure>
</div>
</div>
</div>
<p>And with <code>geom_point</code>:</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1234</span>)</span>
<span id="cb7-2"></span>
<span id="cb7-3">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb7-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">genFun</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><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;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>)</span>
<span id="cb7-5"></span>
<span id="cb7-6">dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb7-7">  <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;">aes</span>(x, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-7-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Parametric equation with dots" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="aesthetic-specifications" class="level3">
<h3 class="anchored" data-anchor-id="aesthetic-specifications">Aesthetic specifications</h3>
<p>The {ggplot2} package has several aesthetic specifications available for plots. A full list can be found <a href="https://ggplot2.tidyverse.org/articles/ggplot2-specs.html">here</a>.</p>
<p>We’re going to go ahead and get rid of all the background using <code>theme_void()</code>.</p>
<section id="size" class="level4">
<h4 class="anchored" data-anchor-id="size">Size</h4>
<p>Let’s go with <code>geom_point</code>. In this case, we can start playing around with the aesthetics to see what would look interesting. With <code>geom_point</code>, you can edit the sizes of the points, so we create a column with random point sizes to create some variation.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1111</span>)</span>
<span id="cb8-2"></span>
<span id="cb8-3">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb8-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">genFun</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><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;">npoints =</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;">%&gt;%</span> </span>
<span id="cb8-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rand_w =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</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;">3000</span>)</span>
<span id="cb8-6"></span>
<span id="cb8-7">dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb8-8">  <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;">aes</span>(x, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-8-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Parametric equation with dots closer together" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="shape" class="level4">
<h4 class="anchored" data-anchor-id="shape">Shape</h4>
<p>We could also change the shape of each of the points, but I liked the circles more:</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb9-2">  <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;">aes</span>(x, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w,</span>
<span id="cb9-4">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-9-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Parametric equation with xes instead of dots" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="opacity" class="level4">
<h4 class="anchored" data-anchor-id="opacity">Opacity</h4>
<p>We could also change the opacity of the points:</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1234</span>)</span>
<span id="cb10-2"></span>
<span id="cb10-3">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb10-4">  dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb10-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rand_o =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</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;">5000</span>)</span>
<span id="cb10-6"></span>
<span id="cb10-7">dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb10-8">  <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;">aes</span>(x, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w,</span>
<span id="cb10-10">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_o) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-10-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Parametric equation with mixed opacity" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="color" class="level4">
<h4 class="anchored" data-anchor-id="color">Color</h4>
<p>We can also create a column for random numbers to ascribe colors to each point. I decided to use the magma color palette from the {viridis} package because it is so vibrant. Now that we’re not using only black points, we can use <code>dark_theme_void()</code> from the {ggdark} package for a fully black background.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1234</span>)</span>
<span id="cb11-2"></span>
<span id="cb11-3">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb11-4">  dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb11-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rand_c =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>()))</span>
<span id="cb11-6"></span>
<span id="cb11-7">dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb11-8">  <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;">aes</span>(x, y,  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> rand_c)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w,</span>
<span id="cb11-10">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_o) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_viridis</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magma"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dark_theme_void</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">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;">"none"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove legend</span></span></code></pre></div></div>
<div class="cell-output-stderr">
<pre><code>Inverted geom defaults of fill and color/colour.
To change them back, use invert_geom_defaults().</code></pre>
</div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-11-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Parametric equation with various colors on a black background" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
</section>
<section id="repetition" class="level3">
<h3 class="anchored" data-anchor-id="repetition">Repetition</h3>
<p>Notice we added <code>rand_w</code>, <code>rand_o</code>, and <code>rand_c</code> so that we can randomly change up the size, opacity, and color of the plot. Let’s go back to our original generative function and them as parameters. Now we can change them without having to add them to the data frame externally from the function. (Apologies for the switching back and forth from dplyr to base R!)</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">genFun <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;">center =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c1 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c2 =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c3 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.28</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c4 =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size_denom =</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;">opacity_denom =</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;">color_denom =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>){</span>
<span id="cb13-2">    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</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>pi, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> npoints)</span>
<span id="cb13-3">    xx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> center[<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> c1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(c2<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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(c2<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;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(c3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>c4<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>t)))</span>
<span id="cb13-4">    yy <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> center[<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> c1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(c2<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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(c3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>c4<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="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(c3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>c4<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>t))</span>
<span id="cb13-5">    rand_w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, npoints, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>size_denom</span>
<span id="cb13-6">    rand_o <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, npoints, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>opacity_denom</span>
<span id="cb13-7">    rand_c <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, npoints, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>color_denom</span>
<span id="cb13-8">    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;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> xx, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> yy, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rand_w =</span> rand_w, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rand_o =</span> rand_o, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rand_c =</span> rand_c)</span>
<span id="cb13-9">    </span>
<span id="cb13-10">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(a)</span>
<span id="cb13-11">}</span></code></pre></div></div>
</div>
<p>Now playing around with the new parameters, I decided to go with this plot:</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1111</span>)</span>
<span id="cb14-2"></span>
<span id="cb14-3">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb14-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">genFun</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">npoints =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c1 =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c2 =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c3 =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c4 =</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;">size_denom =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">opacity_denom =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>)</span>
<span id="cb14-5"></span>
<span id="cb14-6">dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb14-7">  <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;">aes</span>(x, y,  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> rand_c)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w,</span>
<span id="cb14-9">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_o) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_viridis</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magma"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dark_theme_void</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">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;">"none"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove legend</span></span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-13-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Parametric equation with varying dot sizes and colors repeated around the center" width="672"></p>
</figure>
</div>
</div>
</div>
<p>What this allows us to do is change up the generative function and build on our plot. I was interested in rotating the plot around the axis.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1">dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb15-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(x, y,  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> rand_c),</span>
<span id="cb15-4">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w,</span>
<span id="cb15-5">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_o) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>x, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>y,  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> rand_c),</span>
<span id="cb15-7">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w,</span>
<span id="cb15-8">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_o) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>y, x,  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> rand_c),</span>
<span id="cb15-10">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w,</span>
<span id="cb15-11">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_o) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>y, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>x,  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> rand_c),</span>
<span id="cb15-13">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_w,</span>
<span id="cb15-14">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rand_o) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_viridis</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magma"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dark_theme_void</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove legend</span></span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/rtistry-intro/index_files/figure-html/unnamed-chunk-14-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ggsave(here::here("public", "img", "rtistry2.png"), dpi = 320, height = 6, width = 8) # this saves the image</span></span></code></pre></div></div>
</div>
<p>Tada! My first ever #rtistry plot.</p>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>This was my attempt to create generative art in R! It was fun to figure out how on earth to even get started and see how the plots change with new parameters on different attempts. I welcome any thoughts and please share your art using the #rtistry hashtag with <a href="https://twitter.com/ivelasq3">me</a>!</p>
<section id="rtists-i-follow" class="level3">
<h3 class="anchored" data-anchor-id="rtists-i-follow">rtists I follow</h3>
<ul>
<li><a href="https://twitter.com/djnavarro">Danielle Navarro</a></li>
<li><a href="https://twitter.com/ijeamaka_a">Ijeamaka A</a></li>
<li><a href="https://twitter.com/geokaramanis">Georgios Karamanis</a></li>
<li><a href="https://twitter.com/toeb18">Tobias Stalder</a></li>
</ul>
</section>
<section id="packages-for-creating-generative-art" class="level3">
<h3 class="anchored" data-anchor-id="packages-for-creating-generative-art">Packages for creating generative art</h3>
<ul>
<li>djnavarro’s <a href="https://github.com/djnavarro/flametree">flametree</a></li>
<li>ijeamaka_a’s <a href="https://github.com/Ijeamakaanyene/contouR">contourR</a></li>
<li>cutterkom’s <a href="https://github.com/cutterkom/generativeart">generativeart</a></li>
</ul>
<center>
<p><em>Liked this article? I’d love for you to retweet!</em></p>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
New post! 📣 Interested in using <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> to create KidPix-like <a href="https://twitter.com/hashtag/generativeart?src=hash&amp;ref_src=twsrc%5Etfw">#generativeart</a> 🎨 ? Check out my first foray into <a href="https://twitter.com/hashtag/rtistry?src=hash&amp;ref_src=twsrc%5Etfw">#rtistry</a> using a parametric equation here! 👩🏻‍🎨 <a href="https://t.co/ykkddoK5tm">https://t.co/ykkddoK5tm</a><br><br>reposted due to typo 😅 <a href="https://t.co/V5bFSvDsOR">pic.twitter.com/V5bFSvDsOR</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1391947964013285379?ref_src=twsrc%5Etfw">May 11, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>
</section>

 ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/rtistry-intro/</guid>
  <pubDate>Sun, 09 May 2021 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/rtistry-intro/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Exploring other ggplot2 geoms</title>
  <link>https://ivelasq.rbind.io/blog/other-geoms/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/thumbnail-wide.jpg" class="img-fluid figure-img" alt="A person working in fields of colorful tulips with houses in the background"></p>
<figcaption>Vincent Van Gogh, Flower Beds in Holland (1883)</figcaption>
</figure>
</div>
<p>R users are incredibly fortunate to work in an open-source community that creates and shares resources that make our work even better. The {ggplot2} package comes with incredibly useful geoms (geometric objects) to create visualizations. A full list of these can be found in the <a href="https://ggplot2.tidyverse.org/reference/">reference documents</a> for {ggplot2}. These include:</p>
<ul>
<li><code>geom_bar</code> and <code>geom_col</code> for barcharts</li>
<li><code>geom_histogram</code> for histograms</li>
<li><code>geom_point</code> for scatterplots</li>
</ul>
<p>In addition, other amazing folks in the R Community have created geoms that can be used with {ggplot2} and similarly use the tidyverse framework. This is fantastic for many reasons, but some include being able to add themes, facets, titles, and other components just like with any <code>ggplot</code>. Here are a few geoms that I’ve tried out with examples!</p>
<ul>
<li>Streamgraphs using ggstream::geom_stream</li>
<li>Ridgeline plots using ggridges::geom_density_ridges</li>
<li>Sankey diagrams using ggsankey::geom_sankey &amp; ggalluvial::geom_alluvial</li>
<li>Bump charts using ggbump::geom_bump</li>
<li>Waffle charts using waffle::geom_waffle</li>
<li>Beeswarm charts using ggbeeswarm::geom_beeswarm</li>
<li>Mosaic charts using ggmosaic::geom_mosaic</li>
</ul>
<center>
<img src="https://ivelasq.rbind.io/blog/other-geoms/geoms.png" class="img-fluid" alt="Waffle plot, steamgraph, density graph, beeswarm, and mosaic plot">
</center>
<section id="setup" class="level2">
<h2 class="anchored" data-anchor-id="setup">Setup</h2>
<p>To be able to run this code, be sure to have the tidyverse installed. The {wesanderson} package contains beautiful palettes for visualizations.</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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load required packages</span></span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(wesanderson)</span></code></pre></div></div>
</div>
</section>
<section id="streamgraphs" class="level2">
<h2 class="anchored" data-anchor-id="streamgraphs">Streamgraphs</h2>
<p>This post includes three of David Sjöberg’s amazing geoms; he created {ggsankey}, {ggstream}, AND {ggbump}. If you haven’t seen his GitHub, please <a href="https://github.com/davidsjoberg">check it out now</a>.</p>
<p>This first geom, <code>geom_stream()</code>, creates a streamplot (which I’ve also seen called stream graphs). The streamplot is an area graph that usually centers around a central axis and allows us to see large fluctuations over time. More information on streamplot can be found <a href="https://en.wikipedia.org/wiki/Streamgraph">here</a>.</p>
<p>{ggstream} also has other options available to customize the streamgraphs, such as creating an area chart. Check out the repo <a href="https://github.com/davidsjoberg/ggstream">here</a>.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remotes::install_github("davidsjoberg/ggstream")</span></span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggstream)</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(blockbusters, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(year, box_office, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> genre)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb2-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_stream</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb2-6">  <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;">wes_palette</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Darjeeling2"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb2-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/index_files/figure-html/unnamed-chunk-4-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="ridgeline-plots" class="level2">
<h2 class="anchored" data-anchor-id="ridgeline-plots">Ridgeline plots</h2>
<p>The {ggridges} package by Claus O. Wilke package also has a variety of geoms; check out the repo <a href="https://github.com/wilkelab/ggridges">here</a>. Ridgeline plots show the distribution of a numeric value for different groups and can look like mountain ranges. The <a href="https://www.meetup.com/rladies-seattle/">R-Ladies Seattle</a> hex sticker was created using ridgelines (very appropriate for the mountainous Washington!).</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("ggridges")</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggridges)</span>
<span id="cb3-3"> </span>
<span id="cb3-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(blockbusters, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> box_office, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> genre, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> genre)) <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;">geom_density_ridges</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) <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;">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;">wes_palette</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Darjeeling2"</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></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/index_files/figure-html/unnamed-chunk-6-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="sankey-diagrams" class="level2">
<h2 class="anchored" data-anchor-id="sankey-diagrams">Sankey diagrams</h2>
<p>Another geom by David Sjöberg is <code>geom_sankey()</code>, repo <a href="https://github.com/davidsjoberg/ggsankey">here</a>. This geom creates <a href="https://en.wikipedia.org/wiki/Sankey_diagram">Sankey diagrams</a> and <a href="https://en.wikipedia.org/wiki/Alluvial_diagram">alluvial plots</a>, which show flow and transfers in a system or throughout time. These plots are VERY popular on the subreddit <a href="https://www.reddit.com/r/dataisbeautiful/">dataisbeautiful</a> (check it out on Mondays to see some examples).</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># devtools::install_github("davidsjoberg/ggsankey")</span></span>
<span id="cb4-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggsankey)</span>
<span id="cb4-3"></span>
<span id="cb4-4">example_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb4-5">  mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb4-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_long</span>(cyl, vs, am, gear, carb) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># function in ggsankey to format data correctly</span></span>
<span id="cb4-7"></span>
<span id="cb4-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(example_dat,</span>
<span id="cb4-9">       <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, </span>
<span id="cb4-10">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">next_x =</span> next_x, </span>
<span id="cb4-11">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">node =</span> node, </span>
<span id="cb4-12">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">next_node =</span> next_node,</span>
<span id="cb4-13">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(node))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-14">   <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_sankey</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">flow.alpha =</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>
<span id="cb4-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/index_files/figure-html/unnamed-chunk-8-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>Another package for alluvial charts is {ggalluvial} by Jason Cory Brunson, with its repo <a href="https://corybrunson.github.io/ggalluvial/">here</a>. The data can be in more familiar formats than what is required for {ggsankey}.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("ggalluvial")</span></span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggalluvial)</span>
<span id="cb5-3"></span>
<span id="cb5-4"><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;">as.data.frame</span>(UCBAdmissions),</span>
<span id="cb5-5">       <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Freq, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis1 =</span> Gender, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis2 =</span> Dept)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_alluvium</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> Admit), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">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;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wes_palette</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Darjeeling2"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/index_files/figure-html/unnamed-chunk-10-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="bump-charts" class="level2">
<h2 class="anchored" data-anchor-id="bump-charts">Bump charts</h2>
<p>One last one by David Sjöberg is the amazing {ggbump}, repo <a href="https://github.com/davidsjoberg/ggbump">here</a>. Bump plots help show change in rank over time.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># devtools::install_github("davidsjoberg/ggbump")</span></span>
<span id="cb6-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggbump)</span>
<span id="cb6-3"></span>
<span id="cb6-4">blockbusters2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb6-5">  blockbusters <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(genre <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Action"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Comedy"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Drama"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(year) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rank =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rank</span>(box_office))</span>
<span id="cb6-9"></span>
<span id="cb6-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(blockbusters2, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(year, rank, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> genre)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_bump</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_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;">wes_palette</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Darjeeling2"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/index_files/figure-html/unnamed-chunk-12-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="waffle-charts" class="level2">
<h2 class="anchored" data-anchor-id="waffle-charts">Waffle charts</h2>
<p>For waffle charts, which are handy visualizations that show completion or parts of a whole, there is hrbrmstr’s {waffle}. The repo is <a href="https://github.com/hrbrmstr/waffle">here</a>. Check out the ability to bring in other {ggplot2} functions, like <code>facet_wrap</code>. {waffle} also allows you to create pictograms using <code>geom_pictogram</code>, which replaces the squares in the ‘waffle’ with pictures.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("waffle", repos = "https://cinc.rud.is")</span></span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(waffle)</span>
<span id="cb7-3"></span>
<span id="cb7-4"><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;">as_tibble</span>(Titanic), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> Sex, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> n)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_waffle</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_rows =</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;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> Survived, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncol =</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="cb7-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wes_palette</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Darjeeling2"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/index_files/figure-html/unnamed-chunk-14-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="beeswarm-charts" class="level2">
<h2 class="anchored" data-anchor-id="beeswarm-charts">Beeswarm charts</h2>
<p>Beeswarm charts, similar to jitter plots in {ggplot2}, plot individual points showing distributions without allowing the points to overlap too much. Erik Clarke’s repo for {ggbeeswarm} is <a href="https://github.com/eclarke/ggbeeswarm">here</a>.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("ggbeeswarm")</span></span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggbeeswarm)</span>
<span id="cb8-3"></span>
<span id="cb8-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(blockbusters, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> genre, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> box_office, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> genre)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> </span>
<span id="cb8-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_quasirandom</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_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;">wes_palette</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Darjeeling2"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/index_files/figure-html/unnamed-chunk-16-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="mosaic-charts" class="level2">
<h2 class="anchored" data-anchor-id="mosaic-charts">Mosaic charts</h2>
<p>Mosaic charts are incredibly helpful when displaying proportions of (multiple) categories. The {ggmosaic} package by Haley Jeppson (repo <a href="https://github.com/haleyjeppson/ggmosaic">here</a>) uses <code>geom_mosaic</code> to create these visualizations.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># devtools::install_github("haleyjeppson/ggmosaic")</span></span>
<span id="cb9-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggmosaic)</span>
<span id="cb9-3"></span>
<span id="cb9-4"><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;">as.data.frame</span>(UCBAdmissions)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_mosaic</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(Admit, Dept), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> Gender, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">weight =</span> Freq)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_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;">wes_palette</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Darjeeling2"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/other-geoms/index_files/figure-html/unnamed-chunk-18-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="other-geoms" class="level2">
<h2 class="anchored" data-anchor-id="other-geoms">Other geoms</h2>
<p>I know there exist a ton of other geoms that work with {ggplot2} out there. Just as I was writing this blogpost, I discovered {gghilbertstrings}! What other gg packages or geoms do you know of? Let me know on <a href="https://twitter.com/ivelasq3">Twitter</a> and I’ll list them here!</p>
<center>
<p><em>Liked this post? I’d love for you to retweet!</em></p>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
New post 🚀 Into the ggplot2niverse! 🚀 We love geom_point, geom_bar, and the built-in geoms in <a href="https://twitter.com/hashtag/ggplot2?src=hash&amp;ref_src=twsrc%5Etfw">#ggplot2</a> but have you used <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> pkgs with other geoms that use the <a href="https://twitter.com/hashtag/tidyverse?src=hash&amp;ref_src=twsrc%5Etfw">#tidyverse</a> like geom_sankey and geom_waffle? 🐝🧇 See them here &amp; let me know others <br>👉 <a href="https://t.co/orHyDMeVdd">https://t.co/orHyDMeVdd</a> <a href="https://t.co/DxKUxIJI08">pic.twitter.com/DxKUxIJI08</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1376681492030558211?ref_src=twsrc%5Etfw">March 29, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>reference</category>
  <guid>https://ivelasq.rbind.io/blog/other-geoms/</guid>
  <pubDate>Sun, 28 Mar 2021 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/other-geoms/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Preparing a manuscript for publication using bookdown</title>
  <link>https://ivelasq.rbind.io/blog/bookdown-manuscript/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/bookdown-manuscript/thumbnail-wide.png" class="img-fluid figure-img" alt="Rough ocean waves crashing at a rock"></p>
<figcaption>Winslow Homer, Maine Coast (1896)</figcaption>
</figure>
</div>
<p>My co-authors <a href="https://twitter.com/RyanEs">Ryan</a>, <a href="https://twitter.com/efreer20">Emily</a>, <a href="https://twitter.com/kierisi">Jesse</a>, <a href="https://twitter.com/jrosenberg6432">Josh</a>, and <a href="https://twitter.com/ivelasq3">I</a> published our book last year, but <a href="https://datascienceineducation.com/">Data Science in Education Using R</a> is also available online as a bookdown on a website, available to all.</p>
<p><a href="https://www.bookdown.org/">{bookdown}</a> is an R package that facilitates writing books and long-form articles/reports with R Markdown. <a href="">R Markdown</a> is a file format that allows you to write using markdown, a language for formatted text, and integrate R code, analyses, and visualizations. By using R Markdown, my co-authors and I were able to collaborate using familiar scripts, share and run code, and edit our manuscript for publication. By using {bookdown}, we were able to publish these R Markdown files to the web so people could access our book as we were writing it.</p>
<p>We have written <a href="https://education.rstudio.com/blog/2020/10/ds-in-edu/">a</a> <a href="https://rviews.rstudio.com/2020/05/26/community-and-collaboration-writing-our-book-in-the-open/">few</a> <a href="https://rviews.rstudio.com/2020/07/01/open-source-authorship-of-data-science-in-education-using-r/">times</a> about the open and collaborative nature of this work. This article will walk through the more technical aspects of using {bookdown} from our beginners’ standpoint. We hope it highlights the lessons we learned along the way. To peek at the actual files of our book, check out the <a href="https://github.com/data-edu/data-science-in-education">GitHub repo</a>.</p>
<p>So without further ado, here are some tips about {bookdown} that may be helpful on your book manuscript creation:</p>
<ul>
<li>Learning R Markdown and {bookdown}</li>
<li>Snooping on others’ GitHub files</li>
<li>Caching Code Chunks</li>
<li>Figuring out your publisher’s requirements</li>
<li>Determining how to collaborate</li>
</ul>
<section id="learning-r-markdown-and-bookdown" class="level2">
<h2 class="anchored" data-anchor-id="learning-r-markdown-and-bookdown">Learning R Markdown and {bookdown}</h2>
<p>The first place to start to learn {bookdown} is Yihui Xie’s <a href="https://bookdown.org/yihui/bookdown/">bookdown: Authoring Books and Technical Documents with R Markdown</a>. In addition to going into {bookdown}, it provides some information on R Markdown and how to use it as well.</p>
<p>If you are new to R Markdown, Yihui, J. J. Allaire, and Garrett Grolemund wrote a definitive guide, available <a href="https://bookdown.org/yihui/rmarkdown/">here</a>.</p>
<p>These books offer great guidance on {bookdown} and R Markdown, but below are some details if you want to get started with a minimal example of a bookdown.</p>
<section id="ok-you-installed-bookdown.-now-what" class="level3">
<h3 class="anchored" data-anchor-id="ok-you-installed-bookdown.-now-what">OK, you installed {bookdown}. Now what?</h3>
<p>You may notice that a lot of tutorials have you start using {bookdown} with a <a href="https://github.com/rstudio/bookdown-demo/blob/master/index.Rmd">demo project</a>. This is certainly one way to start - exploring the demo project and changing things to see how your book changes when it’s re-rendered. As far as I know, there is no standard template to begin a bookdown. The bare minimum of what you need is an <code>index.Rmd</code> file, your other R Markdown files, a <code>_bookdown.yml</code> file, and <code>_output.yml</code>.</p>
<section id="index.rmd" class="level4">
<h4 class="anchored" data-anchor-id="index.rmd">index.Rmd</h4>
<p>In your project folder, start with an <code>index.Rmd</code> file with title, author, site, and output in the YAML header of the file (the YAML header is the top part of the R Markdown file, see <a href="https://github.com/data-edu/data-science-in-education/blob/master/index.Rmd">here</a> between the <code>---</code>).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode yml 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;">"Test Book"</span></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">author</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;">"Me"</span></span>
<span id="cb1-4"><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;"> bookdown::bookdown_site</span></span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">output</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;"> bookdown::gitbook</span></span>
<span id="cb1-6"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
<p>Below the YAML header, you can use regular R Markdown syntax. Start it off with a first-level header. If you do not want it to be numbered, write <code>{-}</code> beside the header.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Welcome {-}</span></span></code></pre></div></div>
<p>This will be the <em>first page</em> of your rendered book.</p>
</section>
<section id="other-r-markdown-files" class="level4">
<h4 class="anchored" data-anchor-id="other-r-markdown-files">Other R Markdown files</h4>
<p>Besides <code>index.Rmd</code>, other R Markdown files will make up the chapters of your book. <a href="https://bookdown.org/yihui/bookdown/usage.html">By default, bookdown merges all Rmd files by the order of filenames, e.g., 01-intro.Rmd will appear before 02-literature.Rmd</a>. As referenced in Yihui’s book, we named our files with a number first (see <a href="https://github.com/data-edu/data-science-in-education">here</a>].</p>
<p>Some tips:</p>
<p>We recommend each R Markdown file have only <em>one</em> first-level header; otherwise, your chapters will be cut off at any first-level header if you use the K-M rendering approach (see <a href="https://bookdown.org/yihui/bookdown/new-session.html">here</a>). Do not use the same first-level header in the same bookdown!</p>
</section>
<section id="bookdown.yml" class="level4">
<h4 class="anchored" data-anchor-id="bookdown.yml">_bookdown.yml</h4>
<p>Hey, did you notice there’s an underscore in the file name? I didn’t and spent an hour trying to figure out why the book wouldn’t render. So another tip, underscores are important :)</p>
<p>The <code>_bookdown.yml file</code> does not need much. Critical is the <code>book_filename</code> - we used <code>main.Rmd</code>. Here, you also specify the rendering method you would like (mentioned above), and also whether you want to delete the merged file (we recommend yes).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode yml code-with-copy"><code class="sourceCode yaml"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">book_filename</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;">"bookdown-demo"</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">delete_merged_file</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="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb3-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new_session</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="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">yes</span></span></code></pre></div></div>
<p>Besides this, you can add labels to figures and chapters, add scripts to run before each R Markdown file, change the order of your chapters manually (remember, by default it will be index.Rmd then by alphabetical order), and a lot more - but all of that is optional.</p>
</section>
<section id="output.yml" class="level4">
<h4 class="anchored" data-anchor-id="output.yml">_output.yml</h4>
<p>Oh heyy, another underscore!</p>
<p>This file will output your file according to what is specified. It’s also how figure height/width is specified, allows you to specify the TOC, etc. But really, if you want a bookdown all it needs is to know what you want your output to be.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode yml code-with-copy"><code class="sourceCode yaml"><span id="cb4-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bookdown::gitbook</span></span></code></pre></div></div>
</section>
</section>
<section id="rendering-the-book" class="level3">
<h3 class="anchored" data-anchor-id="rendering-the-book">Rendering the book</h3>
<p>OKAY! So you have your files and the bare minimum of what you need to create a bookdown. To see it, go ahead and run:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">bookdown<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">serve_book</span>()</span></code></pre></div></div>
<p>So now you have a bookdown! And you eagerly look at your accomplishment and it is great. But how do we find out what else we can do with {bookdown}?</p>
</section>
</section>
<section id="snooping-on-others-github-files" class="level2">
<h2 class="anchored" data-anchor-id="snooping-on-others-github-files">Snooping on others’ GitHub files</h2>
<p>When I do not know how to do something in R, I look at people who I want to emulate and snoop on their GitHub repository pages. It is so incredibly handy (and wonderful) that others post their code for all to see.</p>
<p>This is how we learned just how to even start using bookdown (copying people’s files, seeing what happened when we ran them), but also the creative ways that others went about customizing their books.</p>
<p>While there’s an <a href="https://bookdown.org/home/archive/">archive</a> of many books using {bookdown}, here are some specific works we used during our bookdown development:</p>
<ul>
<li>Forecasting: Principles and Practice by Rob J Hyndman and George Athanasopoulos (<a href="https://otexts.com/fpp2/">book</a>, <a href="https://github.com/nealxun/Forecasting_Principle_and_Practices">repo</a>) for customizing CSS on a bookdown with custom fonts, colors, etc.</li>
<li>Geocomputation with R by Robin Lovelace, Jakub Nowosad, and Jannes Muenchow (<a href="https://geocompr.robinlovelace.net/">book</a>, <a href="https://github.com/Robinlovelace/geocompr">repo</a>) to learn how to give figures labels.</li>
</ul>
<p>We highly recommend seeing what others have done in the past and trying things out so your book reflects what you would like it to look like!</p>
<section id="customizing-css" class="level3">
<h3 class="anchored" data-anchor-id="customizing-css">Customizing CSS</h3>
<p>Speaking of CSS, this is a nice way to make your bookdown your own. Once you add a <code>css/style.css</code> file in your bookdown repository, you can add <code>css: css/style.css</code> in your <code>_output.yml</code> file. Then, anytime your book renders, it will reference your CSS file. While not explicitly necessary for a manuscript (at least not ours), it is nice to customize one’s work.</p>
<section id="wait-what-if-i-dont-know-css" class="level4">
<h4 class="anchored" data-anchor-id="wait-what-if-i-dont-know-css">Wait, what if I don’t know CSS?</h4>
<p>Do not fret, reader. I also do not know CSS. But thankfully, the <strong>Google Developer Tool</strong> exists.</p>
<p>By right-clicking any part of a web page (including an existing bookdown) in Chrome, you can then click “Inspect Element” to see its HTML file and the hierarchy of the thing you just right-clicked on. Then, by clicking the arrow on the top left of your Inspector pane, you can click on anything to see its HTML file.</p>
<p>This, and a combination of snooping on GitHub, allowed us to find ways to customize our bookdown. <a href="https://github.com/data-edu/data-science-in-education/blob/master/css/style.css">Here</a> is where ours is located and where you can see what is referenced and changed with CSS. For example, this bit of code is saying for the book left-hand pane, when hovering, make the color white and the text <code>#ffbc49</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode css code-with-copy"><code class="sourceCode css"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">.book</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">.book-summary</span> ul<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">.summary</span> li a<span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:hover</span> {</span>
<span id="cb6-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">background-color</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">:</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">#ffffff</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">color</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">:</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">#ffbc49</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-4">}</span></code></pre></div></div>
<p>This process takes a lot of trial and error, I will admit. It may be easier to pick up a bit of CSS if you have specific ideas in mind. However, if you need a quick edit of some pages, seeing how others have done it and exploring with the Developer Tools is very handy.</p>
</section>
</section>
</section>
<section id="caching-code-chunks" class="level2">
<h2 class="anchored" data-anchor-id="caching-code-chunks">Caching code chunks</h2>
<p>As mentioned in Yihui’s book, you can <a href="https://bookdown.org/yihui/bookdown/some-tips.html">cache</a> certain code chunks so they do not have to rerun each time you render the book. We found this very handy, as some complex models took some time to run.</p>
<p>Important to note though: if you use <code>set.seed</code>, you will need to include it in every code chunk; setting it in only one code chunk will not mean it is set for all code chunks.</p>
</section>
<section id="figuring-out-your-publishers-requirements" class="level2">
<h2 class="anchored" data-anchor-id="figuring-out-your-publishers-requirements">Figuring out your publisher’s requirements</h2>
<p>Creating a book using R/R Studio/{bookdown} is great because all of these tools are so versatile and we were able to use each one to meet our publisher requirements, minimize manual work, and reduce redundancies.</p>
<p>For example, here’s how {bookdown} helped us do what we had to do:</p>
<ul>
<li><strong>Our manuscript had to be in Word:</strong> we were able to render the bookdown using Word.</li>
<li><strong>Our manuscript needed all tables and figures to be labeled:</strong> we were able to automate this using the <code>.yml</code> files.</li>
<li><strong>Our figures had to be of a certain size and dimension:</strong> we were also able to automate this using the <code>.yml</code> files.</li>
<li><strong>We needed to send all of our figures separately from the manuscript:</strong> they are all saved separately due to the rendering function of {bookdown}.</li>
<li><strong>We needed a bibliography:</strong> we were able to create a bibliography of works and packages, all automated with {bookdown}.</li>
</ul>
<p>Because of R:</p>
<ul>
<li><strong>All tables had to be in Word format</strong>: at the time, we hadn’t seen this from <a href="https://cran.r-project.org/web/packages/gtsummary/vignettes/rmarkdown.html">{gtsummary}</a>, and we spent quite a bit of time trying to use {gt} for our tables before realizing that we wouldn’t be able to output using Word. We then switched to {sjPlot}, which got us exactly what we needed.</li>
</ul>
<center>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/bookdown-manuscript/gt.png" class="img-fluid figure-img" alt="Table of various table print engines, the functions for creating the tables, and whether they're supported in HTML, PDF, RTF, or Word."></p>
<figcaption>gtsummary Reference</figcaption>
</figure>
</div>
</center>
<ul>
<li><strong>Our bibliography had to be in APA format:</strong> thanks to a file that Josh had (saved <a href="https://github.com/data-edu/data-science-in-education/blob/master/apa_pl.csl">here</a>), all we had to do was save that file and add <code>biblio-style: "apalike"</code> to our <code>index.Rmd</code> file for everything to show up in the format we needed.</li>
</ul>
<p>And, thanks to R Studio:</p>
<ul>
<li>We were able to spell-check files within the IDE!</li>
<li>We used its handy search function to create the index.</li>
</ul>
<p>So, we recommend gathering all of your publisher’s requirements and then mapping them to the different tools at your disposal. This saves a lot of time and headache when it’s finally time to send over the final manuscript.</p>
</section>
<section id="determining-how-to-collaborate" class="level2">
<h2 class="anchored" data-anchor-id="determining-how-to-collaborate">Determining how to collaborate</h2>
<p>Since my co-authors and I all knew GitHub, we decided to use GitHub to write the book. This was great because it was a transparent way of writing the book (non-authors added issues and contributed as they saw fit). We were able to go back in time if needed to fix errors or see what had been changed.</p>
<p>We had to decide how updating the book would work. Ultimately, we decided that one person would be in charge of rendering the book - this helped reduce any code conflicts. However, there may be other ways of working that would be better for you.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>In conclusion, we chose to use {bookdown} to create a book manuscript because we wanted to be transparent in our work, leverage R and its many tools, and be as efficient as possible when writing a book across five people. Despite some technical lift (and a lot of trial and error), it eventually resulted in a smooth workflow for our group. Thanks to the many resources and code available out there, we were able to learn {bookdown} as we wrote. Thanks to {bookdown}, we output the final manuscript that resulted in our book!</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
New blogpost! 🎉 We created our book's manuscript using <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> and <a href="https://twitter.com/hashtag/bookdown?src=hash&amp;ref_src=twsrc%5Etfw">#bookdown</a>! How did we learn how to do it? #1 tip: snoop on other people's GitHub repos 👀 Read more here: <a href="https://t.co/jSozoz86gj">https://t.co/jSozoz86gj</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1369106413079851012?ref_src=twsrc%5Etfw">March 9, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>how-to</category>
  <guid>https://ivelasq.rbind.io/blog/bookdown-manuscript/</guid>
  <pubDate>Mon, 08 Mar 2021 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/bookdown-manuscript/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Remote pair programming in R using Visual Studio Code and Live Share</title>
  <dc:creator>Isabella Velásquez</dc:creator>
  <dc:creator>Gustavo E. Velásquez</dc:creator>
  <link>https://ivelasq.rbind.io/blog/vscode-live-share/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/vscode-live-share/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Two ballerina dancers at the barre, one with her leg in the air"></p>
<figcaption>Edgar Degas, Dancers Practicing at the Barre (1877)</figcaption>
</figure>
</div>
<ul>
<li>The Problem</li>
<li>State of the Code Editors</li>
<li>Installation</li>
<li>Configuration</li>
<li>Writing an R Package Using VS Code</li>
<li>Live Share Tutorial</li>
<li>Final Thoughts</li>
</ul>
<section id="the-problem" class="level2">
<h2 class="anchored" data-anchor-id="the-problem">The problem</h2>
<p>Way back in the <a href="https://www.urbandictionary.com/define.php?term=The%20Before%20Time">Before Time</a>, my <a href="https://github.com/gvelasq">older brother</a> and I worked together on an R package called <a href="https://ivelasq.github.io/wizehiver">{wizehiver}</a>. To collaborate, we used many tools. We had an email thread (of over 35 emails!) that eventually became two email threads. We tried <a href="https://github.com/ivelasq/wizehiver/issues?q=is%3Aissue+is%3Aclosed">GitHub Issues</a>, but we were in such close communication that the back-and-forth on issues was ineffectual. We also tried <a href="https://en.m.wikipedia.org/wiki/Pair_programming">pair programming</a> but since we lived in separate cities, we did it while one of us would share our screen on Skype. We wished there was a better, more hands-on, and immediate way to collaborate in a source code editor in <a href="https://en.wikipedia.org/wiki/Collaborative_real-time_editor">real-time</a>, similar to how seamless it is to work on Google Docs.</p>
</section>
<section id="state-of-the-code-editors" class="level2">
<h2 class="anchored" data-anchor-id="state-of-the-code-editors">State of the code editors</h2>
<p>The <a href="https://rstudio.com/products/rstudio">RStudio IDE</a> is in our opinion the best IDE for R out there; however, live collaboration using RStudio’s <a href="https://docs.rstudio.com/ide/server-pro/r-sessions.html#project-sharing">Project Sharing</a> feature is limited to those with a paid <a href="https://rstudio.com/pricing">RStudio Server Pro</a> license as of this writing. There are many source code editors out there, and notably <a href="https://atom.io/packages/teletype">Atom</a> and <a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare">Visual Studio (VS) Code</a> both provide extensions for free, collaborative real-time editing.</p>
<p>We have been following, with increasing <a href="https://github.com/issues?q=vscode+OR+radian+OR+languageserver+OR+vscDebugger+is%3Aissue+author%3Agvelasq">interest</a>, the growing community of developers who have been focused on tools for R in VS Code. There are now several R packages, VS Code extensions, and a command-line R console available, as well as several tutorials dedicated to R in VS Code. Here we set out to see if VS Code could fill the particular gap we identified in our previous work together — the need for seamless remote pair programming. A few of our use cases are:</p>
<ol type="1">
<li><p>We wanted to collaborate on this blog post in a shared <code>.Rmd</code> file which we could edit and knit as we wrote. Ultimately we wrote most of this post on Google Docs before transferring it to a versioned <code>.Rmd</code> on GitHub for finishing touches.</p></li>
<li><p>We wanted to start collaborating on an open-source R package <a href="https://github.com/gvelasq/mutagen">{mutagen}</a> which will (someday) provide useful extensions to <a href="https://dplyr.tidyverse.org/">{dplyr}</a>’s <a href="https://dplyr.tidyverse.org/reference/mutate.html"><code>mutate()</code></a>:</p></li>
</ol>
<center>
<img src="https://raw.githubusercontent.com/gvelasq/mutagen/master/man/figures/logo.jpeg" class="img-fluid">
</center>
<p>So far, we only have a hex sticker — <a href="https://twitter.com/search?q=%23hexdrivendevelopment">#hexdrivendevelopment</a> in action!</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
but… I… already… know… how… the… hexsticker… should… look…
</p>
— Thomas Lin Pedersen (<span class="citation" data-cites="thomasp85">@thomasp85</span>) <a href="https://twitter.com/thomasp85/status/1022413631340912640?ref_src=twsrc%5Etfw">July 26, 2018</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
<p>Embarrassingly, our last commit to the package was in December 2019. While it would be convenient to blame the pandemic, it was a mix of being busy and other ‘hobby’ projects. However, having a synchronous way of collaborating—where we could see the package being built in action—would enable us to truly get the project underway. Before we begin the tutorial, first we have a public service announcement: if you would like to see Microsoft devote additional resources to support R in VS Code, please upvote R in this <code>vscode-jupyter</code> <a href="https://github.com/microsoft/vscode-jupyter/issues/1536">issue</a>!</p>
</section>
<section id="installation" class="level2">
<h2 class="anchored" data-anchor-id="installation">Installation</h2>
<p>We’re going to use <a href="https://brew.sh/">Homebrew</a> to facilitate installation steps on macOS. We only provide instructions for macOS here, but we do provide links for macOS users who prefer to install applications using the point-and-click method, and for Linux and Windows users to find the correct binaries. We also indicate which steps are optional.</p>
<ol type="1">
<li><p>Open Applications &gt; Utilities &gt; Terminal.</p></li>
<li><p>Install <a href="https://brew.sh/">Homebrew</a> using the terminal command below, also provided on the Homebrew landing page. Paste this code into your terminal:</p></li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/bin/bash</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-fsSL</span> https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span></code></pre></div></div>
<ol type="1">
<li>(Optional) For our favorite free and open-source terminal on macOS, install <a href="https://iterm2.com/">iTerm2</a> by pasting this into your terminal:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cask</span> iterm2</span></code></pre></div></div>
<ol type="1">
<li>If you don’t have them already, you’ll need <a href="https://cloud.r-project.org/">R</a> and <a href="https://rstudio.com/products/rstudio/download/preview/">RStudio Desktop</a>. We’re partial to the preview version of RStudio Desktop which has all the latest features. You can install (and update) them easily from your terminal:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cask</span> r</span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> tap homebrew/cask-versions</span>
<span id="cb3-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cask</span> rstudio-preview</span></code></pre></div></div>
<ol type="1">
<li>Install <a href="https://github.com/randy3k/radian"><code>radian</code></a>, a ‘21st century R console’ and the recommended R console for VS Code.</li>
</ol>
<p><em>Update 2021-02-11</em>: Thanks to the efforts of <a href="https://twitter.com/jdblischak"><code>@jdblischak</code></a> and <a href="https://github.com/randy3k"><code>@randy3k</code></a> in this closed <a href="https://github.com/randy3k/radian/issues/244">issue</a>, <code>radian</code> can now be installed with <a href="https://anaconda.org/conda-forge/radian"><code>conda-forge</code></a> instead of only with <a href="https://pypi.org/project/radian/"><code>pip</code></a>. Most data science tutorials recommend using Python with <a href="https://docs.conda.io/projects/conda/en/latest"><code>conda</code></a> environments, so we suspect that our readers will be more familiar with using <code>conda</code> than <code>pip</code>, as we are. If you do choose to use <code>pip</code> (or <a href="https://snarky.ca/why-you-should-use-python-m-pip/"><code>python -m pip</code></a>), beware that <code>pip</code> <a href="https://www.anaconda.com/blog/using-pip-in-a-conda-environment">should be used carefully</a> inside <code>conda</code> environments.</p>
<p>The steps below first install <a href="https://github.com/conda-forge/miniforge">Miniforge</a>, which we prefer to <a href="https://docs.conda.io/en/latest/miniconda.html">Miniconda</a> since it sets <code>conda-forge</code> as the default channel, then create an empty <code>conda</code> environment named <code>r-console</code> into which we install <code>radian</code> and <a href="https://anaconda.org/conda-forge/jedi"><code>jedi</code></a>. <code>jedi</code> is an optional package that enables Python autocompletion using the <a href="https://rstudio.github.io/reticulate/">{reticulate}</a> R package. Paste this into your terminal:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install miniforge</span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">conda</span> create <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--name</span> r-console</span>
<span id="cb4-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">conda</span> activate r-console</span>
<span id="cb4-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">conda</span> install radian</span>
<span id="cb4-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">conda</span> install jedi <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># for {reticulate} python autocompletion</span></span></code></pre></div></div>
<ol type="1">
<li>In RStudio, install the required R packages for VS Code, namely <a href="https://github.com/REditorSupport/languageserver">{languageserver}</a> from CRAN and the latest GitHub release of <a href="https://github.com/ManuelHentschel/vscDebugger">{vscDebugger}</a>:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" 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;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"languageserver"</span>)</span>
<span id="cb5-2">remotes<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install_github</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ManuelHentschel/vscDebugger"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ref =</span> remotes<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">github_release</span>())</span></code></pre></div></div>
<p>For the tutorial, make sure that you have the following R packages installed, if you don’t already:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" 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;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"devtools"</span>)</span>
<span id="cb6-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dplyr"</span>)</span>
<span id="cb6-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"purrr"</span>)</span>
<span id="cb6-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tibble"</span>)</span>
<span id="cb6-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"usethis"</span>)</span>
<span id="cb6-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vctrs"</span>)</span></code></pre></div></div>
<ol type="1">
<li>Install <a href="https://code.visualstudio.com/">VS Code</a> by pasting this into your terminal:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--cask</span> visual-studio-code</span></code></pre></div></div>
<ol type="1">
<li>Open VS Code and install the following extensions from the Extensions gallery (<code>Shift-Command-X</code>):</li>
</ol>
<!-- -->
<ol type="1">
<li><a href="https://marketplace.visualstudio.com/items?itemName=Ikuyadeu.r">R</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=REditorSupport.r-lsp">R LSP Client</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=RDebugger.r-debugger">R Debugger</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare">Live Share</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-audio">Live Share Audio</a></li>
</ol>
</section>
<section id="configuration" class="level2">
<h2 class="anchored" data-anchor-id="configuration">Configuration</h2>
<ol type="1">
<li>Make sure the <code>r-console</code> environment is still active in your terminal. If it is, your terminal prompt will look like this, or similar:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">r-console</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">~</span> %</span></code></pre></div></div>
<p>If not, then reactivate the <code>r-console</code> environment:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">conda</span> activate r-console</span></code></pre></div></div>
<ol type="1">
<li>Type <code>which radian</code> in your terminal to display the path to the <code>radian</code> executable. Below is what it is on our local machines. Copy the path to your clipboard.</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/usr/local/Caskroom/miniforge/base/envs/r-console/bin/radian</span></span></code></pre></div></div>
<ol type="1">
<li>Determine whether <code>bash</code> or <code>zsh</code> is your default shell. If you don’t know, type this into your terminal:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb11-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$SHELL</span></span></code></pre></div></div>
<p>Older Macs may still use <code>bash</code>, while newer Macs or those with older Macs who have created new user accounts since upgrading to macOS Catalina will likely run <code>zsh</code>, the <a href="https://scriptingosx.com/2019/06/moving-to-zsh">new default macOS shell</a>.</p>
<ol type="1">
<li>Let’s take VS Code for a spin! An useful feature to know about is that typing <code>code &lt;path/file.ext&gt;</code> in your terminal will open a new or existing file in VS Code at the path you specify. Many more details are available in the help page <code>code -h</code>. Depending on whether your default shell is <code>bash</code> or <code>zsh</code>, type <code>code ~/.bashrc</code> or <code>code ~/.zshrc</code> in your terminal to open your shell configuration file, and paste the path you copied in step 2. above to add an alias to <code>radian</code> and bind it to lowercase <code>r</code>:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb12-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> r=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/usr/local/Caskroom/miniforge/base/envs/r-console/bin/radian"</span></span></code></pre></div></div>
<p>You can paste the alias anywhere in the file, but it is probably best to paste it at the very bottom, and avoid inserting it in any preexisting code blocks (e.g., <code>conda initialize</code> blocks) which may be overwritten. Save your configuration file and restart your terminal for the settings to take effect. Now all you need to open <code>radian</code> is to type <code>r</code> in any terminal (Terminal, iTerm2, RStudio, or VS Code)! Useful <code>radian</code> commands to know are:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode zsh code-with-copy"><code class="sourceCode zsh"><span id="cb13-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">q()</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># to exit R, same as with vanilla R and RStudio</span></span>
<span id="cb13-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># to enter shell mode, exit by pressing backspace on an empty line</span></span>
<span id="cb13-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">~</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># to enter {reticulate} python mode, exit by pressing backspace on an empty line</span></span></code></pre></div></div>
<ol type="1">
<li>To configure your <code>.Rprofile</code>, type <code>code ~/.Rprofile</code> in your terminal, or if you are already set up with <a href="https://usethis.r-lib.org">{usethis}</a> in RStudio, run the R command <a href="https://usethis.r-lib.org/reference/edit.html"><code>usethis::edit_r_profile()</code></a>. At a minimum, you will want to enable <a href="https://rstudio.github.io/rstudioapi">{rstudioapi}</a> <a href="https://github.com/Ikuyadeu/vscode-R/wiki/RStudio-addin-support">emulation</a> in VS Code:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">options</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">vsc.rstudioapi =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div></div>
<ol type="1">
<li>To configure <code>radian</code>, type <code>code ~/.radian_profile</code> in your terminal which will open up a new blank editor and create a new file named <code>.radian_profile</code> in the home directory. This is our <a href="https://github.com/gvelasq/dotfiles/blob/master/radian/.radian_profile"><code>.radian_profile</code></a>:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">options</span>(</span>
<span id="cb15-2">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">radian.insert_new_line =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb15-3">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">radian.escape_key_map =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb15-4">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">key =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" &lt;- "</span>),</span>
<span id="cb15-5">        <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;">key =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"m"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" %&gt;% "</span>)</span>
<span id="cb15-6">    )</span>
<span id="cb15-7">)</span></code></pre></div></div>
<p>Save <code>~/.radian_profile</code> and restart your terminal for the settings to take effect.</p>
<ol type="1">
<li>Now we’ll configure VS Code settings. Open VS Code, and navigate to <code>settings.json</code> by using the Command Palette (<code>Shift-Command-P</code>) and navigating to <code>Preferences: Open Settings (JSON)</code>. This is our <a href="https://github.com/gvelasq/dotfiles/blob/master/vscode/settings.json"><code>settings.json</code></a>:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode json code-with-copy"><code class="sourceCode json"><span id="cb16-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb16-2">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Liveshare</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Prompt</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">when</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">receiving</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">focus</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">requests</span></span>
<span id="cb16-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"liveshare.focusBehavior"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"prompt"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-4">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Treat`names.like.this`</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">as</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">one</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">word</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">for</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">selection</span></span>
<span id="cb16-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[r]"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb16-6">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"editor.wordSeparators"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"`~!@#%$^&amp;*()-=+[{]}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">|;:'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\"</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">,&lt;&gt;/?"</span></span>
<span id="cb16-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb16-8">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Use</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">active</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">terminal</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">for</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">all</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">commands</span></span>
<span id="cb16-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.alwaysUseActiveTerminal"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-10">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Use</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">bracketed</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">paste</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">mode</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">when</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">sending</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">code</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">to</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">console</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(radian)</span></span>
<span id="cb16-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.bracketedPaste"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-12">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">or</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">radian</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">path</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">for</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">macOS</span></span>
<span id="cb16-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.rterm.mac"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/usr/local/Caskroom/miniforge/base/envs/r-console/bin/radian"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-14">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Enable</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">session</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">watcher</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(experimental)</span></span>
<span id="cb16-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.sessionWatcher"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-16">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Remove</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">hidden</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">items</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">when</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">clearing</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">R</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">workspace</span></span>
<span id="cb16-17">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.workspaceViewer.removeHiddenItems"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-18">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Telemetry</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Disable</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Microsoft</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">crash</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">reporter</span></span>
<span id="cb16-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"telemetry.enableCrashReporter"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">false</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-20">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Telemetry</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Disable</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Microsoft</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">telemetry</span></span>
<span id="cb16-21">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"telemetry.enableTelemetry"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">false</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-22">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">//</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Terminal</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Path</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">to</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">integrated</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">shell</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">on</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">macOS</span></span>
<span id="cb16-23">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"terminal.integrated.shell.osx"</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/bin/zsh"</span></span>
<span id="cb16-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The <code>r.rterm.mac</code> field above should be the path to <code>radian</code> if you followed the <code>radian</code> installation instructions above, otherwise it should be the path to your <code>R</code> executable (if you don’t know it, type <code>which R</code> in your terminal). Since we use Homebrew to install the latest <code>zsh</code> using <code>brew install zsh</code>, the path to our <code>zsh</code> is <code>/usr/local/bin/zsh</code>, but we have put <code>/bin/zsh</code> above since that is the default <code>zsh</code> location for most macOS users. You should run <code>which r</code> and <code>which zsh</code> to confirm your local settings are correct.</p>
</div>
</div>
<ol type="1">
<li>Below are some useful <a href="https://github.com/Ikuyadeu/vscode-R/wiki/Keyboard-shortcuts">keyboard shortcuts</a> for <code>keybindings.json</code>, found by using the Command Palette (<code>Shift-Command-P</code>) in VS Code and navigating to <code>Preferences: Open Keyboard Shortcuts (JSON)</code>. This is our <a href="https://github.com/gvelasq/dotfiles/blob/master/vscode/keybindings.json"><code>keybindings.json</code></a>:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode json code-with-copy"><code class="sourceCode json"><span id="cb17-1"><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span></span>
<span id="cb17-2">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-3">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"View: Show R Workspace"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-4">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"alt+r"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-5">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"workbench.view.extension.workspaceViewer"</span></span>
<span id="cb17-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-8">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R: Create R Terminal"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-9">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"alt+`"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-10">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.createRTerm"</span></span>
<span id="cb17-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-13">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R: Insert Assignment Operator"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-14">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"alt+-"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-15">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-16">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"when"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"editorLangId == r || editorLangId == rmd &amp;&amp; editorTextFocus"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-17">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"args"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"text"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" &lt;- "</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb17-18">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-20">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R: Insert Pipe Operator"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-21">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shift+cmd+m"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-22">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-23">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"when"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"editorLangId == r || editorLangId == rmd &amp;&amp; editorTextFocus"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-24">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"args"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"text"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" %&gt;% "</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb17-25">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-27">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R: Insert Assignment Pipe Operator"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-28">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shift+cmd+,"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-29">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-30">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"when"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"editorLangId == r || editorLangId == rmd &amp;&amp; editorTextFocus"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-31">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"args"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"text"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" %&lt;&gt;% "</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb17-32">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-33">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-34">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R: Insert Tee Pipe Operator"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-35">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shift+cmd+."</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-36">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-37">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"when"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"editorLangId == r || editorLangId == rmd &amp;&amp; editorTextFocus"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-38">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"args"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"text"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" %T&gt;% "</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb17-39">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-40">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-41">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R: Test Package"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-42">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shift+cmd+8"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-43">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.test"</span></span>
<span id="cb17-44">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-45">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-46">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R: Document"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-47">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shift+cmd+9"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-48">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.document"</span></span>
<span id="cb17-49">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-50">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb17-51">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"description"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R: Load All"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-52">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"key"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shift+cmd+0"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-53">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"command"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r.loadAll"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb17-54">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb17-55"><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span></span></code></pre></div></div>
</section>
<section id="writing-an-r-package-using-vs-code" class="level2">
<h2 class="anchored" data-anchor-id="writing-an-r-package-using-vs-code">Writing an R Package using VS Code</h2>
<p>In this section we’re going to set up a toy R package in VS Code, and in the next section we will enable Live Share.</p>
<ol type="1">
<li><p>Open VS Code and use the Command Palette (<code>Shift-Command-P</code>) to navigate to <code>R: Create R Terminal</code>, or use the suggested keyboard shortcut above (<code>Option-`</code>). Note that if you have an editor open and the focus is on the editor, for the shortcut to work you may first need to use <code>Control-`</code> for <code>View: Toggle Integrated Terminal</code> followed by <code>Option-`</code> for <code>R: Create R Terminal</code>. If our configuration above worked for you, these commands should open a terminal instance with the <code>radian</code> console, and the title of the terminal should be <code>1: R Interactive</code> (or <code>2: R Interactive</code> if it’s the second active terminal).</p></li>
<li><p>In the VS Code R console, create a {mutagen} package folder on your Desktop, declare dependencies, and start an R script for a new function <code>cast_integers()</code>:</p></li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(usethis)</span>
<span id="cb18-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">create_package</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~/Desktop/mutagen"</span>)</span>
<span id="cb18-3">deps <span class="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;">"dplyr"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"purrr"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tibble"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vctrs"</span>)</span>
<span id="cb18-4">purrr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">walk</span>(deps, use_package)</span>
<span id="cb18-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">use_r</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cast_integers"</span>)</span></code></pre></div></div>
<ol type="1">
<li><p>In VS Code, open the {mutagen} folder using File &gt; Open… (<code>Command-O</code>) and selecting the <code>mutagen</code> folder in the Desktop. This will open a new VS Code instance and the title bar will read <code>Welcome — mutagen</code>. The R extension icon will be visible on the sidebar since VS Code will detect the <code>.R</code> file in the folder.</p></li>
<li><p>Use the Explorer icon in the sidebar (<code>Shift-Command-E</code>) and open the <code>cast_integers.R</code> file. Paste the following code into the editor and save the file:</p></li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' Safely cast numeric columns to integers</span></span>
<span id="cb19-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#'</span></span>
<span id="cb19-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' `cast_integers()` casts all eligible numeric columns in a data frame to integers, without data loss, using `vctrs::vec_cast()` for coercion.</span></span>
<span id="cb19-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' @param .data A data frame</span></span>
<span id="cb19-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' @return A tibble. If the input data frame has rownames, these will be preserved in a new rowname column.</span></span>
<span id="cb19-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' @examples (mtcars_integerized &lt;- cast_integers(mtcars))</span></span>
<span id="cb19-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#' @export</span></span>
<span id="cb19-8">cast_integers <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>(.data) {</span>
<span id="cb19-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.data.frame</span>(.data))</span>
<span id="cb19-10">    .data <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames_to_column</span>(.data)</span>
<span id="cb19-11">    .data <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_tibble</span>(.data)</span>
<span id="cb19-12">    int_index <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> purrr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map_lgl</span>(</span>
<span id="cb19-13">        .data,</span>
<span id="cb19-14">        <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">inherits</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">try</span>(vctrs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vec_cast</span>(.x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">to =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">integer</span>()), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">silent =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"try-error"</span>)</span>
<span id="cb19-15">    )</span>
<span id="cb19-16">    .data <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> 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;">mutate</span>(</span>
<span id="cb19-17">        .data,</span>
<span id="cb19-18">        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;">across</span>(</span>
<span id="cb19-19">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.cols =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(int_index))),</span>
<span id="cb19-20">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.fns =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> vctrs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vec_cast</span>(.x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">to =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">integer</span>())</span>
<span id="cb19-21">        )</span>
<span id="cb19-22">    )</span>
<span id="cb19-23">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(.data)</span>
<span id="cb19-24">}</span></code></pre></div></div>
<ol type="1">
<li>Now create a new R console in VS Code using either the keyboard shortcuts (<code>Control-`</code> to toggle the terminal and <code>Option-`</code> to create an R console) or by opening the Command Palette (<code>Shift-Command-P</code>) and navigating to <code>R: Create R Terminal</code>. Focus your view on the R extension by clicking R the sidebar (<code>Option-R</code>), and now test out the package. Below are a series of R console commands to familiarize you with the package development workflow in VS Code. We will load the package, document it, and create a new object in the R workspace that uses the new function we just loaded onto the package environment. To get familiar with the VS Code user interface, we will also print the object in the console, view it with the data viewer, and check out the help file for our new function.</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb20-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb20-2">devtools<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load_all</span>() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># or Shift-Command-0 using keyboard shortcuts above</span></span>
<span id="cb20-3">devtools<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">document</span>() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># or Shift-Command-9 using keyboard shortcuts above</span></span>
<span id="cb20-4">mtcars_integerized <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> mtcars <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cast_integers</span>()</span>
<span id="cb20-5">mtcars_integerized</span>
<span id="cb20-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">View</span>(mtcars_integerized)</span>
<span id="cb20-7">?cast_integers</span></code></pre></div></div>
</section>
<section id="live-share-tutorial" class="level2">
<h2 class="anchored" data-anchor-id="live-share-tutorial">Live share tutorial</h2>
<p>Now that we’ve started writing our R package in VS Code, it’s time to Live Share! Microsoft has a handy walkthrough <a href="https://docs.microsoft.com/en-us/visualstudio/liveshare/use/vscode">here</a>, but we will explain what we did and detail R project idiosyncrasies that we found.</p>
<p>In order to host a Live Share collaboration session, first you’ll need to sign into Visual Studio Live Share. Click on the <code>Live Share</code> status bar item or press <code>Shift-Command-P</code> and navigate to <code>Live Share: Sign In With Browser</code>. A notification will appear asking you to sign into either a Microsoft or GitHub account using your default web browser.</p>
<p>Once you are signed in, open a folder or file for pair programming. For package development, this would be the project folder for the package (e.g., the {mutagen} folder we created above). Click the <code>Live Share</code> status bar item or type <code>Shift-Command-P</code> and navigate to <code>Live Share: Start Collaboration Session (Share)</code>. An invite link will be copied automatically to your clipboard. You can send this link to your collaborator(s) and allow them to join a new session that shares the contents of the folder. Once a collaborator clicks the link, a notification will prompt you to approve the guest before they can join. Please note that guests do not necessarily need to be signed into to collaborate using Live Share, since anonymous guests are allowed; however, the host will need to be signed in. In fact, <a href="https://docs.microsoft.com/en-us/visualstudio/liveshare/quickstart/browser-join">guests don’t even need to have VS Code installed and can join Live Share from a browser</a>!</p>
<p>Once a guest has joined a collaboration session, all collaborators will immediately be able to see each other’s cursors, edits, and selections in real-time. You can pick a file from the Explorer (<code>Shift-Command-E</code>) and start editing. Both hosts and guests will see edits as they are made.</p>
<p>As we worked on {mutagen} files, we noticed the usual loading of a package in development, via <code>devtools::load_all()</code>, or sourcing an entire file using <code>Shift-Command-S</code> (the VS Code version of RStudio’s <code>Shift-Command-Enter</code>), will not work for the guest. Why? Because the path to the folder directory is different for the host and guest. In our example, instead of the host’s path <code>~/Desktop/mutagen/R/cast_integers.R</code>, the guest’s path was an abbreviated <code>/R/cast_integers.R</code>, which led to errors when loading and sourcing from keyboard shortcuts. However, the guest can still run the code themselves (such as by selecting and running the source code in an R script, or using <code>Command-Enter</code> line by line) as long as they do not try to source the entire package. We did not try to abstract the path-generating rules for the guests’ Live Share instance into new keyboard shortcuts, but this seems like a solvable problem to allow guests to run <code>devtools::load_all()</code> or <code>source()</code> with minor modifications. Another gotcha was the R workspace; we tried to toggle the setting <code>"liveshare.publishWorkspaceInfo": true</code> in <code>settings.json</code>, but it did not let us share the R workspace between host and guest. It appears that for now host and guest(s) can only maintain separate R workspaces, though it would be useful to have the option to share the R s and its objects.</p>
</section>
<section id="final-thoughts" class="level2">
<h2 class="anchored" data-anchor-id="final-thoughts">Final thoughts</h2>
<p>We’re excited for the future of R programming in VS Code. Live Share is an outstanding innovation for collaborative real-time editing, and is only one of the many amazing features in VS Code. Here we have only scratched the surface of use cases for Live Share. Microsoft keeps a running list of <a href="https://docs.microsoft.com/en-us/visualstudio/liveshare/reference/use-cases">many other Live Share use cases</a>.</p>
<p>We are also huge fans of RStudio and the RStudio IDE. On our wish list for RStudio is that a live collaboration feature be supported in future versions of RStudio Desktop (not only the Pro version) and RStudio Cloud. Having many excellent options is a good thing! In the meantime, it is clear that VS Code is maturing into a capable IDE for R. Live Share is an attractive and free feature that enables real-time collaboration for the masses and that we hope others will enjoy as much as we have.</p>
<center>
<p><em>Liked this post? I’d love for you to retweet!</em></p>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
🎉📢🎉 Collaborating in <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a>? Git got you down? Want to code with others remotely, in real-time, and for free (à la Google Docs)? Check out how to set up and use <a href="https://twitter.com/code?ref_src=twsrc%5Etfw"><span class="citation" data-cites="code">@code</span></a> (<a href="https://twitter.com/hashtag/vscode?src=hash&amp;ref_src=twsrc%5Etfw">#vscode</a>) and <a href="https://twitter.com/hashtag/vsliveshare?src=hash&amp;ref_src=twsrc%5Etfw">#vsliveshare</a> for remote <a href="https://twitter.com/hashtag/pairprogramming?src=hash&amp;ref_src=twsrc%5Etfw">#pairprogramming</a> 🤝 in R! 🤯. Tutorial here: <a href="https://t.co/Qbrw71V77Z">https://t.co/Qbrw71V77Z</a> <a href="https://t.co/3sy9hAJea7">pic.twitter.com/3sy9hAJea7</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1357136366568689664?ref_src=twsrc%5Etfw">February 4, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>how-to</category>
  <guid>https://ivelasq.rbind.io/blog/vscode-live-share/</guid>
  <pubDate>Wed, 03 Feb 2021 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/vscode-live-share/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Browse and search liked Tweets using R</title>
  <link>https://ivelasq.rbind.io/blog/get-tweet-likes/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/get-tweet-likes/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Abstract blue and white birds repeating on against a white and blue background"></p>
<figcaption>Rijksmuseum, Pigeons in white and blue (1928)</figcaption>
</figure>
</div>
<p>The other day, I was scrolling through my “liked” Tweets and got maybe 100 deep when I accidentally clicked a hyperlink and had to restart scrolling from the beginning. The experience made me so frustrated that I started looking up easier ways of perusing one’s likes. I found <a href="https://medium.com/@xoelop/how-to-browse-and-search-your-liked-tweets-711fc1b70851">this tutorial</a> that walked through how to pull liked Tweets into a CSV using Python - so I decided to give it a shot using R.</p>
<section id="set-up-your-project" class="level2">
<h2 class="anchored" data-anchor-id="set-up-your-project">Set up your project</h2>
<p>For this tutorial, I set up a project with the following structure. I walk through how to create <code>like.js</code> and <code>like_csv.csv</code> in the walkthrough.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode md code-with-copy"><code class="sourceCode markdown"><span id="cb1-1">+-- code.R</span>
<span id="cb1-2">+-- data</span>
<span id="cb1-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span>   +-- like.js</span>
<span id="cb1-4">+-- output</span>
<span id="cb1-5"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span>   +-- likes_csv.csv</span></code></pre></div></div>
</section>
<section id="getting-liked-tweets" class="level2">
<h2 class="anchored" data-anchor-id="getting-liked-tweets">Getting liked Tweets</h2>
<section id="step-1-download-your-twitter-archive" class="level3">
<h3 class="anchored" data-anchor-id="step-1-download-your-twitter-archive">Step 1: Download your Twitter archive</h3>
<p>Like the Python tutorial, you have to first download your Twitter archive. Go to https://twitter.com/settings/your_twitter_data, enter your password, and “Download Archive”. You will get an email when you can download your data - for me, it took a day.</p>
<p>Once downloaded, open the ZIP file. Save the <code>like.js</code> file in your project’s <code>data</code> folder.</p>
</section>
<section id="step-2-load-the-js-file-and-convert-it-to-a-data-frame" class="level3">
<h3 class="anchored" data-anchor-id="step-2-load-the-js-file-and-convert-it-to-a-data-frame">Step 2: Load the JS file and convert it to a data frame</h3>
<p>Now, start an <code>R</code> script (I called mine <code>code.R</code>). Install (if you haven’t already) and load all the packages.</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;">library</span>(tidyverse)</span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(rjson)</span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(rtweet)</span></code></pre></div></div>
</div>
<p>The <code>like.js</code> file is a Javascript file. To convert it to a data frame, first convert to a JSON file by removing the text that makes it Javascript, read in the JSON, and then flatten into a data frame using <code>purrr::flatten_df</code>.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">js <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_file</span>(here<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">here</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"like.js"</span>))</span>
<span id="cb3-2">json <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sub</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"window.YTD.like.part0 = "</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>, js)</span>
<span id="cb3-3"> </span>
<span id="cb3-4">likes_raw <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb3-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fromJSON</span>(json)</span>
<span id="cb3-6"></span>
<span id="cb3-7">likes_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb3-8">  likes_raw <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb3-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">flatten_df</span>()</span></code></pre></div></div>
</div>
<p>Now your likes, their status IDs, and URLs are stored in <code>likes_df</code>.</p>
</section>
<section id="step-3-authenticate-rtweet-and-get-tweet-info" class="level3">
<h3 class="anchored" data-anchor-id="step-3-authenticate-rtweet-and-get-tweet-info">Step 3: Authenticate {rtweet} and get tweet info</h3>
<p>To get the Tweet info, you have to authenticate your Twitter account and get the API keys. Go to your <a href="https://developer.twitter.com/en/portal/projects-and-apps">Twitter Developer Portal</a> to do this. The {rtweet} vignette <a href="https://cran.r-project.org/web/packages/rtweet/vignettes/auth.html">here</a> covers what to do pretty well, but one thing I noticed is now you have to enable “3-legged OAuth” and there, you can add the Callback URL of <code>http://127.0.0.1:1410</code> (otherwise you will get a 401 error when running the code below).</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">token <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">create_token</span>(</span>
<span id="cb4-3">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">consumer_key =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PUT API KEY IN QUOTES HERE"</span>,</span>
<span id="cb4-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">consumer_secret =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PUT API KEY SECRET IN QUOTES HERE"</span></span>
<span id="cb4-5">  )</span></code></pre></div></div>
</div>
<p>Once your <code>token</code> is saved, you can use <code>rtweet::lookup_statuses</code> to get the Tweet info.</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">likes_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb5-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lookup_statuses</span>(likes_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>tweetId)</span></code></pre></div></div>
</div>
<p>There you have it! All your likes and their information are saved in the <code>likes_dat</code> data frame. Here, you can do all of your usual data manipulations - <code>lookup_statuses()</code> results in a LOT of data, so I recommend narrowing it down to the columns you care about using <code>select()</code>.</p>
</section>
<section id="step-4-save-to-a-csv" class="level3">
<h3 class="anchored" data-anchor-id="step-4-save-to-a-csv">Step 4: Save to a CSV</h3>
<p>Saving to a CSV is a bit tricky because <code>lookup_statuses()</code> creates list-columns, which cannot be exported to a CSV.</p>
<p>Here, I’ve selected only the columns <code>status_id</code>, <code>text</code>, and <code>hashtags</code> to look at. <code>hashtags</code> is a list-column because one Tweet may have multiple hashtags, which is then saved as a vector within the column <code>hashtags</code>. To convert it to a data frame, I use <code>unnest()</code>. This creates a data frame with multiple entries for each Tweet, one for each hashtag.</p>
<p>That is too long for me since I want to quickly look through my likes. I then create a hashtag ID for each tweet by grouping by the <code>status_id</code> and assigning each of its hashtags an ID using <code>row_number()</code> and then using <code>pivot_wider()</code> to move each hashtag into its own column.</p>
<p>You will see that some tweets have blank entries while some tweets have many!</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">likes_csv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb6-2">  likes_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(status_id, text, hashtags) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unnest</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(status_id) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">row_number</span>()) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_wider</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_prefix =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hashtag_"</span>,</span>
<span id="cb6-8">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_from =</span> id,</span>
<span id="cb6-9">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_from =</span> hashtags)</span></code></pre></div></div>
</div>
<p>Now, this is savable in a CSV. You can run the code below if your project has an <code>output</code> folder.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write_csv</span>(likes_csv, here<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">here</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"output"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"likes_csv.csv"</span>))</span></code></pre></div></div>
</div>
<p>Thank you for reading this quick entry in looking through your Twitter likes. I hope this reduces the amount of annoying scrolling you need to do to look through your Tweets! I think there are a lot of opportunities to make this an even easier process - maybe a Shiny app? - but hopefully, this is a good starting point.</p>
<center>
<em>Liked this post? I’d love for you to retweet!</em>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Are you, too, constantly frustrated there's no way to easily look through your liked Tweets on Twitter? 🐦 😤 You can save all of your liked tweets into a CSV using R and {rtweet}! Quick tutorial here: <a href="https://t.co/etoOaczTwa">https://t.co/etoOaczTwa</a> <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1326550008548585472?ref_src=twsrc%5Etfw">November 11, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>
</section>

 ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/get-tweet-likes/</guid>
  <pubDate>Tue, 10 Nov 2020 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/get-tweet-likes/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>An even easier-to-use R package for school district shapefiles</title>
  <link>https://ivelasq.rbind.io/blog/leaidr2/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/leaidr2/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Abstract painting of black rectangles on a yellow background"></p>
<figcaption>Piet Mondrian, Tableau No.&nbsp;2/Composition No.&nbsp;VII (1913)</figcaption>
</figure>
</div>
<section id="an-update-to-leaidr" class="level2">
<h2 class="anchored" data-anchor-id="an-update-to-leaidr">An update to leaidr</h2>
<p>A few months ago, I created <a href="https://github.com/ivelasq/leaidr">{leaidr}</a> for easier download of U.S. school district shapefiles. <a href="https://github.com/datalorax">Daniel Anderson</a> went through and greatly improved the package, making it even easier to download and use the shapefiles (thanks Dan!).</p>
<p>Now, instead of having to run <code>lea_prep()</code>, you can download the shapefiles from Dan’s Github repository like so:</p>
<div class="cell" data-layout-align="center" data-hash="index_cache/html/unnamed-chunk-2_39a8649a452d2d0a34547b5043cdf2e4">
<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>(leaidr)</span>
<span id="cb1-2"></span>
<span id="cb1-3">tn <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lea_get</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tn"</span>)</span></code></pre></div></div>
<div class="cell-output-stdout">
<pre><code>OGR data source with driver: ESRI Shapefile 
Source: "/private/var/folders/pj/nmg9b8_93dq4kwt8nt2d4cj40000gn/T/RtmpqlCmYd/47", layer: "47"
with 158 features
It has 18 fields</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">tn <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb3-2">  sf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_as_sf</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb3-3">  ggplot2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-4">  ggplot2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_sf</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/leaidr2/index_files/figure-html/unnamed-chunk-2-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Blank map of Tennessee school districts." width="672"></p>
</figure>
</div>
</div>
</div>
<p>And, if you use <code>lea_get()</code> (i.e., with <code>state = NULL</code>), you’ll get the shapefiles for the whole U.S. back via ROpenSci’s {piggyback}.</p>
<p>So much easier and better!</p>
<p>Because Dan helped make the package so great, I wanted to add on and showcase what can be done with it! So, today’s post is jam-packed with choices…</p>
<ul>
<li>Create a beautiful map in Mapbox</li>
<li>Create a Shiny app with your beautiful map</li>
<li>Add a Shiny app to a package</li>
</ul>
</section>
<section id="create-a-beautiful-map-in-mapbox" class="level2">
<h2 class="anchored" data-anchor-id="create-a-beautiful-map-in-mapbox">Create a beautiful map in Mapbox</h2>
<p>Asmae Toumi wrote a <a href="https://asmae-toumi.netlify.app/posts/2020-08-10-how-to-make-web-ready-us-county-level-maps/">blog post</a> on how to make maps using R and Mapbox. So, I figured: why not announce the new and improved {leaidr} functions to create a beautiful Mapbox map??</p>
<p>This walkthrough will go a little deeper with Mapbox, as I am an extreme beginner and had to do a lot of investigating to figure out how to use it.</p>
<p>I suggest first reading through Asmae’s tutorial as there are a few things you need to do before being able to run the below: download the {mapboxapi} package, create a Mapbox account, and install Tippecanoe.</p>
<section id="load-the-packages" class="level3">
<h3 class="anchored" data-anchor-id="load-the-packages">Load the packages</h3>
<p>Here are the packages you will need:</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;">library</span>(tidyverse)</span>
<span id="cb4-2"></span>
<span id="cb4-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remotes::install_github("walkerke/mapboxapi")</span></span>
<span id="cb4-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(mapboxapi)</span>
<span id="cb4-5"></span>
<span id="cb4-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># if you haven't installed the package yet</span></span>
<span id="cb4-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># devtools::install_github("ivelasq/leaidr")</span></span>
<span id="cb4-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(leaidr)</span>
<span id="cb4-9"></span>
<span id="cb4-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(rmapshaper)</span>
<span id="cb4-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(mapdeck)</span></code></pre></div></div>
</div>
</section>
<section id="download-the-data" class="level3">
<h3 class="anchored" data-anchor-id="download-the-data">Download the data</h3>
<p>Download your shapefiles. If you want to make a choropleth map, also read in the data that you will append to your shapefiles and merge them by a common ID. (Sorry for using a local file!)</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">shp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># leaidr shapefiles</span></span>
<span id="cb5-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lea_get</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;">"or"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"wa"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb5-3">  sf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_as_sf</span>()</span>
<span id="cb5-4"></span>
<span id="cb5-5">dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># data to append </span></span>
<span id="cb5-6">  <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;">"/Users/shortessay/Downloads/ccd_lea_141_1819_l_1a_091019/ccd_lea_141_1819_l_1a_091019.csv"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb5-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(ST <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OR"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"WA"</span>))</span>
<span id="cb5-8"></span>
<span id="cb5-9">northwest <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb5-10">  shp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb5-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(GEOID, geometry) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb5-12">  sp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">merge</span>(dat, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by.x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GEOID"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by.y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LEAID"</span>)</span></code></pre></div></div>
</div>
</section>
<section id="create-the-tileset" class="level3">
<h3 class="anchored" data-anchor-id="create-the-tileset">Create the tileset</h3>
<p>Now, following the original tutorial, we use Tippecanoe to optimize the shapefiles and data and then upload the “tiles” to Mapbox.</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;">tippecanoe</span>(</span>
<span id="cb6-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input =</span> northwest,</span>
<span id="cb6-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">output =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nw.mbtiles"</span>,</span>
<span id="cb6-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">layer_name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"northwest"</span>)</span>
<span id="cb6-5"></span>
<span id="cb6-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">upload_tiles</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nw.mbtiles"</span>,</span>
<span id="cb6-7">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">username =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ivelasq3"</span>, </span>
<span id="cb6-8">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tileset_id =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"northwest"</span>,</span>
<span id="cb6-9">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">multipart =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div></div>
</div>
</section>
<section id="style-the-tiles" class="level3">
<h3 class="anchored" data-anchor-id="style-the-tiles">Style the tiles</h3>
<p>This is the part that I had to figure out on the Mapbox website. <a href="https://docs.mapbox.com/help/tutorials/choropleth-studio-gl-pt-1/">This</a> walkthrough was helpful. Once you have uploaded the tiles using <code>upload_tiles()</code>, you should see them available under “Custom tileset” at the bottom of this webpage: https://studio.mapbox.com/tilesets/.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/leaidr2/1.png" class="img-fluid figure-img" alt="Screenshot of Mapbox website with Tilesets"></p>
<figcaption>Mapbox Tilesets</figcaption>
</figure>
</div>
<p>Then, go to Styles on this webpage: https://studio.mapbox.com/. Click “New Style” and choose the template you want, then Customize.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/leaidr2/2.png" class="img-fluid figure-img" alt="Screenshot of Mapbox choosing a template"></p>
<figcaption>Mapbox Template</figcaption>
</figure>
</div>
<p>To add your tileset, go to Layers, click the Plus sign, then under “Source”, find your uploaded tileset, or add the tileset by the ID given by <code>upload_tiles()</code>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/leaidr2/3.png" class="img-fluid figure-img" alt="Screenshot of Mapbox layers and how to add them"></p>
<figcaption>Mapbox Layers</figcaption>
</figure>
</div>
<p>I zoomed to where my tiles are located (Oregon and Washington) and started editing. <a href="https://docs.mapbox.com/help/tutorials/choropleth-studio-gl-pt-1/#data-driven-styling">This section of the walkthrough</a> explains how to create a choropleth map, where each geography has a different color according to a value.</p>
<p>Once done styling, I clicked “Publish” on the top right of Mapbox Studio.</p>
</section>
<section id="using-the-map-in-r" class="level3">
<h3 class="anchored" data-anchor-id="using-the-map-in-r">Using the map in R</h3>
<p>To get the information to bring it back into R and be able to use the map in a Shiny app, I clicked “Share” and scrolled to find the Style ID.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/leaidr2/4.png" class="img-fluid figure-img" alt="Screenshot of Mapbox sharing a map"></p>
<figcaption>Mapbox Sharing</figcaption>
</figure>
</div>
<p>I copied the Share URL to include in the function below. For the location parameter, I used the latitude/longitude listed in the browser URL. I played around with the zoom level until I found one I liked.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mapdeck</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">token =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Sys.getenv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MAPBOX_PUBLIC_TOKEN"</span>),</span>
<span id="cb7-2">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">style =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mapbox://styles/ivelasq3/ckehhzzld3l3p19mht1n8hksj"</span>,</span>
<span id="cb7-3">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">zoom =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,</span>
<span id="cb7-4">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">location =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">120.161</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">45.843</span>))</span></code></pre></div></div>
</div>
</section>
</section>
<section id="create-a-shiny-app-with-your-beautiful-map" class="level2">
<h2 class="anchored" data-anchor-id="create-a-shiny-app-with-your-beautiful-map">Create a Shiny app with your beautiful map</h2>
<p>Once you have the <code>mapdeck()</code> function all set up, you can use it in a Shiny app. <a href="https://github.com/greghuang8/Geovis/blob/master/shinyApp.R">Here’s</a> some reference code that I found useful for using <code>renderMapdeck()</code>. Thank you Greg Huang!</p>
<p>This is an example of a very bare-bones Shiny app. For the UI, use <code>mapdeckOutput()</code>:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(shiny)</span>
<span id="cb8-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(mapdeck)</span>
<span id="cb8-4"></span>
<span id="cb8-5">ui <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fluidPage</span>(</span>
<span id="cb8-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mapdeckOutput</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outputId =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"createMap"</span>)</span>
<span id="cb8-7">)</span></code></pre></div></div>
</div>
<p>And for the server, paste the <code>mapdeck()</code> function in <code>renderMapdeck()</code>:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">server <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>(input, output) {</span>
<span id="cb9-2"></span>
<span id="cb9-3">  output<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>createMap <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">renderMapdeck</span>({</span>
<span id="cb9-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mapdeck</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">token =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Sys.getenv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MAPBOX_PUBLIC_TOKEN"</span>),</span>
<span id="cb9-5">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">style =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mapbox://styles/ivelasq3/ckehhzzld3l3p19mht1n8hksj"</span>,</span>
<span id="cb9-6">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">zoom =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,</span>
<span id="cb9-7">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">location =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">120.161</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">45.843</span>))</span>
<span id="cb9-8">  })</span>
<span id="cb9-9">}</span></code></pre></div></div>
</div>
<p>I uploaded the app <a href="https://ivelasq.shinyapps.io/leaidr/">here</a>.</p>
</section>
<section id="add-a-shiny-app-to-a-package" class="level2">
<h2 class="anchored" data-anchor-id="add-a-shiny-app-to-a-package">Add a Shiny app to a package</h2>
<p>Now, say you would like to add the Shiny app to your package as well as upload it to shinyapps.io / instead of uploading to shinyapps.io. Thankfully, Dean Attali has a <a href="https://deanattali.com/2015/04/21/r-package-shiny-app/">great walkthrough</a> on how to do this!</p>
<ol type="1">
<li>Add {shiny} to your dependencies in your <code>DESCRIPTION</code> file (I do this with <code>usethis::use_package("shiny")</code>).</li>
<li>Create a folder called <code>inst</code> in your package with another folder for the Shiny example, and your UI/server file(s) within.</li>
<li>Create an R file to run your example (I used <code>usethis::use_r("runExample.R")</code>) to create this file.</li>
<li>Don’t forget to document! <code>devtools::document()</code></li>
</ol>
<p>So, if you were to install and load {leaidr}, you can run <code>leaidr::runExample()</code> to launch the Shiny app. To see what the files look like, check out the Github repo files <a href="https://github.com/ivelasq/leaidr/tree/master/inst/shiny-examples/mapbox">here</a>.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>In conclusion, {leaidr} can help you map your data as long as you have school district LEAID’s or names in there somewhere. I hope that it helps you in your education data projects!</p>
<center>
<p><em>Liked this article? I’d love for you to retweet!</em></p>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
New goodies for leaidr, an <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> pkg for school district shapefiles!<br><br>🤩 Major upgrade thx to <a href="https://twitter.com/datalorax?ref_src=twsrc%5Etfw"><span class="citation" data-cites="datalorax">@datalorax</span></a><br>📓 New docs: <a href="https://t.co/yOszd3SG7e">https://t.co/yOszd3SG7e</a><br>🗺️ Mapbox example thx to <a href="https://twitter.com/asmae_toumi?ref_src=twsrc%5Etfw"><span class="citation" data-cites="asmae_toumi">@asmae_toumi</span></a><br>🌐 Shiny app IN package thx to <a href="https://twitter.com/daattali?ref_src=twsrc%5Etfw"><span class="citation" data-cites="daattali">@daattali</span></a><br>ℹ️ Walkthrough: <a href="https://t.co/i2I121b6a3">https://t.co/i2I121b6a3</a><br><br>Happy mapping 🤓 <a href="https://t.co/4hIgJ9evoX">pic.twitter.com/4hIgJ9evoX</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1300446746955452416?ref_src=twsrc%5Etfw">August 31, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>tutorial</category>
  <category>reference</category>
  <guid>https://ivelasq.rbind.io/blog/leaidr2/</guid>
  <pubDate>Sun, 30 Aug 2020 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/leaidr2/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Party with R: How the community enabled us to write a book</title>
  <link>https://ivelasq.rbind.io/blog/party-with-R/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/party-with-R/thumbnail-wide.jpg" class="img-fluid figure-img" alt="A dancer with a large skirt dancing at a dance hall with a crowd behind her"></p>
<figcaption>Henri de Toulouse-Lautrec, Marcelle Lender Dancing the Bolero in Chilpéric (1895-1896)</figcaption>
</figure>
</div>
<blockquote class="blockquote">
<p>It is like a party all the time; nobody has to worry about giving one or being invited; it is going on every day in the street and you can go down or be part of it from your window. - Eleanor Clark</p>
</blockquote>
<p>Without the R community, <a href="https://www.datascienceineducation.com/"><em>Data Science in Education Using R</em></a> would never have happened. Most evidently, we wouldn’t have met each other without the strong R presence on Twitter that sparked a conversation about data use in education. More importantly though, are the aspects of the R community that inspired that initial discussion and enabled us to complete a book for a broad and complex field.</p>
<p>In the <a href="https://datascienceineducation.com/c01.html">first chapter of our book</a>, we invite data practitioners in education to the party but the R community invited us to the party first. Like any successful party, certain elements had to exist for us to join in and end up having an amazing time.</p>
<p><strong>The Invitation</strong> 📩</p>
<p>As someone who started following the R community on Twitter after it was already well established and popular, I never felt the apprehension about having to ask how to get involved or interact with others. First, there are so many avenues. The R community offers many ways to let you in, whether it be replying to Tweets, posting a question on community.rstudio.com, or sharing a blog post on R Weekly. Second, the R community welcomes users no matter their level. Whether it is a code snippet with a function you found cool, a blog post, or a personal side project, there are ways to engage that appeal to everybody. Members of the R community can interact how they want and as often as they want.</p>
<p>For us, it was exciting to meet on Twitter, talk about collaborating on an education data project, and then just get started on it. We felt welcome and encouraged to do so. Because people in the R community meet other users virtually and begin side projects all the time, we didn’t have to worry about whether something like this was possible: The invitation was already there.</p>
<p><strong>An Open Door</strong> 🚪</p>
<p>In our first blog post, we described what it’s like to learn by seeing someone do the thing you want to learn. One of the best things about the R community is you constantly get to see this in action. The R community not only holds open principles but actually exhibits them whenever possible. Users post their code, projects, and drafts constantly. Just by scanning the #rstats hashtag, one can discover something new.</p>
<p>Because others were open, we knew that we wanted to be open as well. We wrote our book on <a href="https://github.com/data-edu/data-science-in-education">GitHub</a>, showing all the many changes it went through until its final completion. By having it freely available on a <a href="https://www.datascienceineducation.com/">website</a>, we hope that it opens the door to others who’d like to learn what we did and work on their own open project as well.</p>
<p><strong>Food (for Thought)</strong> 🍕</p>
<p>The R community offers so many opportunities to get feedback, advice, and information from a wide variety of users. Early on in the book development, we had a lot of questions to nail down: who is the audience? “Data is” or “data are?” How do we describe “people who work in the education field and use data and want to get more effective at it?” Finding a common language was difficult, but we were able to do this by engaging others in the wider R community. We listened to the stories of many data scientists who work in education, then found common experiences we could describe in our writing.</p>
<p>As an example, we learned we weren’t the only ones challenged by learning a programming language while attending to full-time jobs and personal lives. Knowing this, we made sure to <a href="https://datascienceineducation.com/c02.html#different-strokes-for-different-data-scientists-in-education">discuss these challenges in our book</a> and offer various ways of engaging with the material based on the reader’s needs.</p>
<p><strong>Socializing</strong> 💬</p>
<p>Throughout the process of writing DSIEUR, we asked the R community several times for other types of feedback and suggestions. We also ran into some technical issues, especially when it came to preparing our manuscript with {bookdown} to meet our publisher’s specifications, and were able to get ideas on how to resolve them. We know that the R community is a safe and encouraging place to ask questions, and this enabled us to write a stronger book.</p>
<p><strong>The Next Day</strong> ☀️</p>
<p>The community participation throughout the DSIEUR process helped us define our goals and get feedback. Another wonderful aspect is that the R community engaged us back. Writing this RViews series is an example: Someone reached out to us and wanted us to reflect on what we discovered and share it with all of you. This type of engagement reminds us of what an inclusive and encouraging place the R community is and helps us come up with new ways of making sure others see the invitation as well.</p>
<p>Thank you for reading! 🎉 We’ll be back with the fourth post on “One Writer, Five Authors” in about two weeks. Until then, we’d love to know how else the R paRty has encouraged your work, both personally and professionally. You can reach us on Twitter: Emily <a href="https://twitter.com/ebovee09"><strong>ebovee09</strong></a>, Jesse <a href="https://twitter.com/kierisi"><strong>kierisi</strong></a>, Joshua <a href="https://twitter.com/jrosenberg6432"><strong>jrosenberg6432</strong></a>, Ryan <a href="https://twitter.com/RyanEs"><strong>RyanEs</strong></a>, and me <a href="https://twitter.com/ivelasq3"><strong>ivelasq3</strong></a>.</p>
<center>
<em>Liked this post? I’d love for you to retweet!</em>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Party with R: How the Community Enabled Us to Write a Book<a href="https://t.co/NnGqM9Ux2X">https://t.co/NnGqM9Ux2X</a>
</p>
— RStudio (<span class="citation" data-cites="rstudio">@rstudio</span>) <a href="https://twitter.com/rstudio/status/1290688259182526466?ref_src=twsrc%5Etfw">August 4, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
<p><i>This was originally posted on <a href="https://rviews.rstudio.com/2020/08/03/party-with-r-how-the-community-enabled-us-to-write-a-book/">RViews</a></i>.</p>



 ]]></description>
  <category>explanation</category>
  <guid>https://ivelasq.rbind.io/blog/party-with-R/</guid>
  <pubDate>Mon, 13 Jul 2020 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/party-with-R/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>What it takes to tidy Census data</title>
  <link>https://ivelasq.rbind.io/blog/tidying-census-data/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/thumbnail-wide.jpg" class="img-fluid figure-img" alt="A town of people skating on a frozen lake"></p>
<figcaption>Hendrick Avercamp, Ice-skating in a Village (1610)</figcaption>
</figure>
</div>
<p>The U.S. Census releases aggregate data on their <a href="https://www.census.gov/data/tables/2020/demo/hhp2.html">Household Pulse Survey</a>. These data are valuable and cover a range of important topics, particularly those related to the COVID-19 pandemic.</p>
<p>First of all, let me clarify that I think that the work that the Census does is amazing and I am so glad that these data are available. But, when you download the data, you will see that it is a highly stylized Excel spreadsheet. There may be upsides for those who want to see the data quickly and easily. As an R user though, seeing all those merged cells, non-numeric numerics, and category names in rows makes me feel <code>emo::ji('unamused')</code>.</p>
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census_image.png" class="img-fluid" alt="One of the Census Excel spreadsheets pointing out egregious formatting, like headers, merged cells, and categories in rows."></p>
<p>However, this is not terribly surprising (and with public data, somewhat expected). As stated in the <a href="https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html">tidy data</a> paper:</p>
<blockquote class="blockquote">
<p>It is often said that 80% of data analysis is spent on cleaning and preparing data.</p>
</blockquote>
<p>Thankfully, we have the very powerful R and tidyverse available to address our data woes. Let’s go through the process of tidying these data with tidyverse packages to show how easily they can become ready for analysis!</p>
<section id="loading-the-data" class="level2">
<h2 class="anchored" data-anchor-id="loading-the-data">Loading the data</h2>
<p>As usual, we begin by loading our packages.</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>(tidyverse)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(readxl)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(httr)</span></code></pre></div></div>
</div>
<p>We have the option to download the Excel file and load it in R. But what if we want to load the data directly from the website? We can use {httr}! The following code ‘gets’ the file from the internet, writes it in a temporary file path, and loads it in an object called <code>path</code>.</p>
<blockquote class="blockquote">
<p>Many thanks to Liz Potamites for pointing out: if the below doesn’t work, it may be that the link is changed or broken. It should be Table 2 from the second week of the Household Pulse Survey, which as of July 21, 2020, is located <a href="https://www.census.gov/data/tables/2020/demo/hhp/hhp2.html">here</a>.</p>
</blockquote>
<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;">GET</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www2.census.gov/programs-surveys/demo/tables/hhp/2020/wk2/educ2_week2.xlsx"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write_disk</span>(path <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tempfile</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fileext =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".xlsx"</span>)))</span></code></pre></div></div>
<div class="cell-output-stdout">
<pre><code>Response [https://www2.census.gov/programs-surveys/demo/tables/hhp/2020/wk2/educ2_week2.xlsx]
  Date: 2022-03-13 15:45
  Status: 200
  Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  Size: 442 kB
&lt;ON DISK&gt;  /var/folders/pj/nmg9b8_93dq4kwt8nt2d4cj40000gn/T//RtmpRY4m58/file2eca17a48009.xlsx</code></pre>
</div>
</div>
</section>
<section id="cleaning-the-data" class="level2">
<h2 class="anchored" data-anchor-id="cleaning-the-data">Cleaning the data</h2>
<p>As mentioned in the figure above, each sheet comprises a state’s data. It’d be good to have all of the data in one single data structure. One option is to try to force all of the sheets together at once in a data frame (which is a 2D structure). But we also saw that each sheet requires a lot of cleaning before it can be useful, and it may be difficult to clean if they’re all merged in one data frame. Therefore, let’s instead first read in all the data as a <strong>list</strong> (which is a higher dimension structure), clean it up, and <em>then</em> put it together in a data frame.</p>
<p>However, I am not very good at thinking about things in a list format and it’s a little harder to see what’s going on compared to looking at a data frame using <code>View()</code>. Before I clean up a list, I usually work on a single cut of the list as a data frame to know what exactly I am going to do. Thankfully, all the sheets in this Excel sheet are formatted the same across states. This isn’t always the case! Because they are identically formatted, we know if our processing works on one sheet, it will work across all of them.</p>
<p>Let’s look at a single sheet!</p>
<section id="single-sheet-cleaning" class="level3">
<h3 class="anchored" data-anchor-id="single-sheet-cleaning">Single sheet cleaning</h3>
<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">census_sheet1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_excel</span>(path, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sheet =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">View</span>(census_sheet1)</span></code></pre></div></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census1.png" class="img-fluid figure-img" alt="First three columns of the imported dataset, first column is the table title and the other two don't have names and are listed as dot dot dot 2 and dot dot dot 3."></p>
<figcaption>First three columns of the imported dataset</figcaption>
</figure>
</div>
<p>Immediately, we see that the top lines are superfluous rows (the headers from the original dataset). We can use <code>skip</code> in <code>read_excel()</code> to not have them read in.</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">census_sheet1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb5-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_excel</span>(path, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sheet =</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;">skip =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb5-3"></span>
<span id="cb5-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># View(census_sheet1)</span></span></code></pre></div></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census2.png" class="img-fluid figure-img" alt="Dataset with skipped lines so that the column names are now characteristics, Total, and impact of the pandemic on children's education."></p>
<figcaption>Dataset with skipped lines</figcaption>
</figure>
</div>
<p>Now that the unnecessary rows are gone, we see that the column names aren’t reading in super well because of the merged cells in the original sheet. In this case, we manually create a vector of the column names and replace the old ones with <code>set_names()</code>.</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">new_names <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb6-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"select_characteristics"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"using_online_resources"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"using_paper_materials_sent_home"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"where_classes_were_cancelled"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"where_classes_changed_in_another_way"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"where_no_change_to_classes"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"did_not_respond"</span>)</span>
<span id="cb6-3"></span>
<span id="cb6-4">census_example <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb6-5">  census_sheet1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb6-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_names</span>(new_names)</span></code></pre></div></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census3.png" class="img-fluid figure-img" alt="Dataset with cleaned names so that they are select underscore characteristics, total, and using online resources."></p>
<figcaption>Dataset with cleaned names</figcaption>
</figure>
</div>
<p>We still have some empty rows (and also a row at the very bottom which is a note in the original dataset). We can eliminate these rows using <code>slice()</code>. Here, we’re saying to ‘slice’ rows 1 through 3 and 60.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">census_example <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb7-2">  census_example <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb7-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">slice</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</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;">61</span>)</span></code></pre></div></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census4.png" class="img-fluid figure-img" alt="Dataset with removed rows so that the first rows start to line up with the columns."></p>
<figcaption>Dataset with removed rows</figcaption>
</figure>
</div>
<p>Now to deal with the fact that the category names are embedded within the first column <code>select_characteristics</code>. There may be other ways to do this, but again I manually create a vector with all the values that I want to get rid of and use <code>filter()</code> to keep only the rows that do <strong>not</strong> contain the items in the vector.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">filter_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb8-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Age"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sex"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hispanic origin and Race"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Education"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Marital status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Presence of children under 18 years old"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Respondent or household member experienced loss of employment income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean weekly hours spent on…"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Respondent currently employed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Food sufficiency for households prior to March 13, 2020"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Household income"</span>)</span>
<span id="cb8-3"></span>
<span id="cb8-4">census_example <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb8-5">  census_example <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb8-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>select_characteristics <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> filter_var) </span></code></pre></div></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census5.png" class="img-fluid figure-img" alt="Dataset with filtered rows so that the columns and rows match up."></p>
<figcaption>Dataset with filtered rows</figcaption>
</figure>
</div>
<p>Even though we removed the characteristic names from the rows, they contain very useful information. Also, we run into an issue in which two of the characteristic categories had the same options (“yes” and “no”). If we don’t address this, we’ll forget which rows are for which characteristic. To fix this, we manually create a column with the characteristics for each of the response options and append it to the data.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">category_column <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb9-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"age"</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;">"age"</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;">"age"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"race"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"race"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"race"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"race"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"race"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"education"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"education"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"education"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"education"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"marital_status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"marital_status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"marital_status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"marital_status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"marital_status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"children"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"children"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"loss_employment"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"loss_employment"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"loss_employment"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hours_spent"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hours_spent"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"employed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"employed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"employed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"food_sufficiency"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"food_sufficiency"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"food_sufficiency"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"food_sufficiency"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"food_sufficiency"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"income"</span>)</span>
<span id="cb9-3"></span>
<span id="cb9-4">census_example <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb9-5">  census_example <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb9-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_column</span>(category_column)</span></code></pre></div></div>
</div>
<center>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census6.png" class="img-fluid figure-img" alt="Column with variable names that repeat down the column."></p>
<figcaption>Column with variable names</figcaption>
</figure>
</div>
</center>
<p>Finally, you may have noticed that some of the rows did not read in as numbers but as characters.</p>
<center>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census7.png" class="img-fluid figure-img" alt="Column with numbers but with character type."></p>
<figcaption>Column with numbers but with character type</figcaption>
</figure>
</div>
</center>
<p>We can use <code>mutate_at()</code> and specify which variables we want to be numeric.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">census_example <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb10-2">  census_example <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb10-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate_at</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vars</span>(total, using_online_resources<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>did_not_respond), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</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;">as.numeric</span>(.)))</span></code></pre></div></div>
</div>
<p>Hooray - now we have a tidy dataset we could use for analysis! Which is great, but it’s only one sheet. How do we do this for the additional 66?</p>
</section>
<section id="multi-sheet-cleaning" class="level3">
<h3 class="anchored" data-anchor-id="multi-sheet-cleaning">Multi-sheet cleaning</h3>
<p>We will now download the data and store it in a list, where each sheet (which represents a state) is saved as a tibble within the list. To work across all the lists, we use the tidyverse package {purrr} and its handy functions.</p>
<p>You may notice that the multi-sheet cleaning looks a lot like the single sheet cleaning but everything is wrapped in the function <code>map()</code>. That’s true! The wonderful thing about {purrr} being in the tidyverse is that it’s really easy to integrate with all the tidyverse functions.</p>
<p>Reading the data into one list is slightly more complicated than reading in a single sheet. We begin with the file path from before and then use <code>excel_sheets()</code> to create a vector of the sheet names. <code>set_names()</code> ensures that we have a named list that contains the state names, which will be important later. If we don’t use <code>set_names()</code>, then the tibbles have generic names instead of ‘US’, ‘AL’, etc. Then using <code>purrr::map()</code>, we ask R to download each of the sheets of the dataset and store it together in a list (<code>map()</code> always returns a list).</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">census_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb11-2">  path <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb11-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">excel_sheets</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb11-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_names</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb11-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</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;">read_excel</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">path =</span> path, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sheet =</span> .x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">skip =</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;">.id =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sheet"</span>)</span></code></pre></div></div>
</div>
<p>If you take a look at the list using <code>View(census_list)</code>, you can see the data is stored as tibbles within the list. If you expand <code>US</code>, you’ll see the same data as when we did the single sheet example. You can also see the same data if you run <code>census_list[["US"]]</code>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/census_list.png" class="img-fluid figure-img" alt="Viewing the list of each state with the same data structure underneath"></p>
<figcaption>Viewing the list</figcaption>
</figure>
</div>
<p>Using the same thinking as we did with the single sheet example, let’s go through and clean up this list - without having to go into each tibble!</p>
<p>First, we set the names within each list using <code>set_names()</code>. We tell <code>map()</code> the names of the columns by defining <code>nm</code>.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">census_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb12-2">  census_list <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb12-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(., set_names, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nm =</span> new_names)</span></code></pre></div></div>
</div>
<p>For each tibble in the list (<code>.x</code>), remove the rows 1 through 3 and 60.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">census_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb13-2">  census_list <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb13-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</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;">slice</span>(.x, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</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;">61</span>))</span></code></pre></div></div>
</div>
<p>Now for each tibble, filter out the rows in <code>select_characteristics</code> that contain the items in <code>filter_var</code>.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">census_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb14-2">  census_list <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb14-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</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;">filter</span>(.x, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>select_characteristics <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> filter_var))</span></code></pre></div></div>
</div>
<p>Like before, we want a new column that lets us know the category for each of the characteristic options.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1">census_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb15-2">  census_list <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb15-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</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;">add_column</span>(.x, category_column))</span></code></pre></div></div>
</div>
<p>And like before, we want to make sure our numeric columns are actually numeric.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">census_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb16-2">  census_list <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb16-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</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;">mutate_at</span>(.x, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vars</span>(total, using_online_resources<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>did_not_respond), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</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;">as.numeric</span>(.))))</span></code></pre></div></div>
</div>
<p>Now that our tibbles are all clean and uniform, let’s make this a single, 2D data frame! As I mentioned before, our list should contain the state abbreviations. We can use <code>map_df()</code> to create a data frame with an ID column called <code>state</code> that stores each of the sheet names. With this column, we’ll easily know which column is for which state/geography.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1">census_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> </span>
<span id="cb17-2">  census_list <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb17-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map_df</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;">as.data.frame</span>(.x), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.id =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"state"</span>)</span></code></pre></div></div>
</div>
<p>Congrats! We have successfully tidied a Census dataset!</p>
</section>
</section>
<section id="using-the-data" class="level2">
<h2 class="anchored" data-anchor-id="using-the-data">Using the data</h2>
<p>The purpose of all this work is to be able to use it easily in R and with the tidyverse specifically. Let’s use the plotting package {ggplot2} to make something!</p>
<p>According to the Census website, we can calculate percentages by removing those that did not respond from the total for the denominator (let’s presume that NA in the column means that everybody responded). Let’s say we want to see the proportion of respondents in the U.S. who say their classes were canceled by income level.</p>
<div class="cell" data-layout-align="center">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">census_us_income <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb18-2">  census_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb18-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(state <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;">"US"</span>, category_column <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;">"income"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb18-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">responses =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">case_when</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(did_not_respond) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> total <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> did_not_respond, </span>
<span id="cb18-5">                               <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(did_not_respond) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> total),<span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># calculate denominator</span></span>
<span id="cb18-6">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pct_cancelled =</span> where_classes_were_cancelled <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> responses) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># calculate percentage</span></span>
<span id="cb18-7"></span>
<span id="cb18-8">census_us_income <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># setting factor levels so graph shows correct order</span></span>
<span id="cb18-9">  census_us_income <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb18-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">select_characteristics =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(select_characteristics,</span>
<span id="cb18-11">                                         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Less than $25,000"</span>, </span>
<span id="cb18-12">                                                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$25,000 - $34,999"</span>,</span>
<span id="cb18-13">                                                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$35,000 - $49,999"</span>,</span>
<span id="cb18-14">                                                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$50,000 - $74,999"</span>,</span>
<span id="cb18-15">                                                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$75,000 - $99,999"</span>,</span>
<span id="cb18-16">                                                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$100,000 - $149,999"</span>,</span>
<span id="cb18-17">                                                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$150,000 - $199,999"</span>,</span>
<span id="cb18-18">                                                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$200,000 and above"</span>)))</span>
<span id="cb18-19"></span>
<span id="cb18-20">census_us_income <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb18-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(select_characteristics <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;">"Did not report"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb18-22">  <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;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> select_characteristics, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> pct_cancelled)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_bar</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stat =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"identity"</span>,</span>
<span id="cb18-24">           <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;">"#00C3DA"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-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="cb18-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;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">angle =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-27">  <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="cb18-28">  <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;">"Percent of Respondents Whose Children's Classes Were Cancelled"</span>,</span>
<span id="cb18-29">       <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;">"Income"</span>,</span>
<span id="cb18-30">       <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;">"Percent with Classes Cancelled"</span>,</span>
<span id="cb18-31">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">caption =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Source: U.S. Census"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/tidying-census-data/index_files/figure-html/unnamed-chunk-34-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Barplot showing percent of classes that were cancelled by income group, with lower income groups more likely to report cancelled classes" width="672"></p>
</figure>
</div>
</div>
</div>
<p>From this graph, we can see that respondents from the lower-income bands were more likely to say that classes were canceled for their children due to COVID.</p>
<center>
<p><em>Liked this article? I’d love for you to retweet!</em></p>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
New blogpost 📣: What It Takes to Tidy Census Aggregate Data! ⭐ Let's take all those heavily formatted Excel sheets and make them a plain and simple data frame together! <a href="https://t.co/IsPb8BJ0ZT">https://t.co/IsPb8BJ0ZT</a> <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> <a href="https://t.co/XABr07wYfP">pic.twitter.com/XABr07wYfP</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1266372221179588609?ref_src=twsrc%5Etfw">May 29, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>tutorial</category>
  <guid>https://ivelasq.rbind.io/blog/tidying-census-data/</guid>
  <pubDate>Thu, 28 May 2020 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/tidying-census-data/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Introducing an R package for school district shapefiles</title>
  <link>https://ivelasq.rbind.io/blog/leaidr-shapefiles/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/leaidr-shapefiles/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Colorful flowers in a pot with a black background"></p>
<figcaption>Abraham Mignon, Still Life with Flowers and a Watch (1660 - 1679)</figcaption>
</figure>
</div>
<p>I would like to introduce <a href="https://github.com/ivelasq/leaidr">{leaidr}</a>, a package for mapping U.S. school district shapefiles!</p>
<p>Inspired by my coauthor <a href="https://joshuamrosenberg.com/">Joshua Rosenberg</a>, the goal of {leaidr} is to facilitate the download and use of school district shapefiles.</p>
<p>School districts in the U.S. have associated local education agency identification numbers (LEAID) used in the <a href="https://nces.ed.gov/pubs2010/100largest0809/tables/table_d05.asp">National Center for Education Statistics (NCES) Common Core of Data</a>. These are very useful because if you have other datasets with NCES IDs, then you can (sometimes easily) join them.</p>
<p>It can be very useful to visualize districts and associated data. District shapefiles are available in different places, such as through the <a href="https://nces.ed.gov/programs/edge/Geographic/DistrictBoundaries">NCES</a> and <a href="https://exhibits.stanford.edu/data/catalog/db586ns4974">Stanford Education Data Archive</a>. The package {tigris} also has a school district option, but unfortunately, it is missing a few district polygons.</p>
<div class="cell" data-layout-align="center">
<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>(tigris)</span>
<span id="cb1-2"></span>
<span id="cb1-3">ca <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tigris<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">school_districts</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">state =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"06"</span>,</span>
<span id="cb1-4">                               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"unified"</span>)</span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(ca[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GEOID"</span>])</span></code></pre></div></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/leaidr-shapefiles/index_files/figure-html/unnamed-chunk-2-1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" alt="Map of school districts from tigris, which is missing quite a few districts." width="672"></p>
</figure>
</div>
</div>
</div>
<p>{leaidr} downloads NCES’ U.S. district shapefile from Github using ROpenSci’s <a href="https://github.com/ropensci/piggyback">{piggyback}</a> package. This is a super helpful package, as Github caps file uploads at 100 MB (and the shapefile is ~170 MB). I originally tried Github Large File Storage (LFS), but it stores files as a hash, not as an actual file. Therefore, I couldn’t figure out how to use it for a package that others can use.</p>
<p>The function <code>lea_get()</code> downloads an R Data file from the Github repo to your designated path and then writes the necessary shapefiles. Then, create an object with <code>lea_prep()</code> by designating where the shapefiles exist and which state(s) you would like. <strong>Note:</strong> For now, you must use the state’s FIPS code. FIPS state codes are numeric and two-letter alphabetic codes to identify U.S. states and certain other associated areas. A reference table is found <a href="https://www.mcc.co.mercer.pa.us/dps/state_fips_code_listing.htm">here</a>.</p>
<p>Once you have the shapefile, then you can merge with other datasets and plot using packages like {leaflet} and {ggplot2}.</p>
<section id="example-of-creating-a-school-district-map" class="level2">
<h2 class="anchored" data-anchor-id="example-of-creating-a-school-district-map">Example of creating a school district map</h2>
<p>Let’s walk through an example where we will merge external data to the shapefile and then map all the districts in California. The external data is from Josh’s <a href="https://github.com/making-data-science-count/covidedu"><code>covidedu</code> project</a>, which scrapes district websites for specific words. In this case, the search terms were “covid*”, “coron*”, and “closure”. I highly recommend using <code>covidedu</code> for easy scraping from a <strong>lot</strong> of district websites!</p>
<p>First, let’s call our packages.</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;">library</span>(tidyverse)</span>
<span id="cb2-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># if you haven't installed the package yet</span></span>
<span id="cb2-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># devtools::install_github("ivelasq/leaidr")</span></span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(leaidr)</span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(maptools)</span>
<span id="cb2-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># if you don't have this downloaded</span></span>
<span id="cb2-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("mapproj")</span></span></code></pre></div></div>
</div>
<p>Time to get your data! Use {leaidr} to download and prep your shapefiles for California (FIPS == 06). Read in the external data (in this case, <code>summary-of-table-of-links.csv</code>).</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>You must have a GitHub PAT set to run <code>lea_get()</code>. <a href="https://happygitwithr.com/github-pat.html">Happy git with R</a> has a great walkthrough on how to get one if you do not have it already.</p>
</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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># download the shapefile into a designated folder</span></span>
<span id="cb3-2">leaidr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lea_get</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">path =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"./test"</span>)</span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># prep the shapefile for the state(s) you'd like</span></span>
<span id="cb3-5">ca_shapefile <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb3-6">  leaidr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lea_prep</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">path =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"./test"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fips =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"06"</span>)</span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># read in the external data that also has NCES ID's</span></span>
<span id="cb3-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this is from the covidedu project</span></span>
<span id="cb3-10">ca_data <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb3-11">  <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;">"https://raw.githubusercontent.com/making-data-science-count/covidedu/master/output/2020-04-29/summary-of-table-of-links.csv"</span>)</span></code></pre></div></div>
</div>
<p>Join the CSV to the shapefile.</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">ca_merge <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb4-2">  sp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">merge</span>(ca_shapefile, ca_data, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by.x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GEOID"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by.y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nces_id"</span>)</span></code></pre></div></div>
</div>
<p>Now ‘fortify’ the data - this converts the polygons into points. This is so that ggplot can create the plot.</p>
<p>If you get the error <code>isTRUE(gpclibPermitStatus()) is not TRUE</code>, then you need to enable <code>gpclib</code> by running <code>gpclibPermit()</code> (this is part of the {maptools} package, which should have been loaded above). Note that support for <code>gpclib</code> will be withdrawn from maptools at the next major release, so you might have to try something else if the package has been upgraded.</p>
<p>If you run <code>gpclibPermit()</code> and you keep getting <code>FALSE</code>, then you are missing the package {gpclib}. Install the package, then run <code>gpclibPermit()</code> to set it to <code>TRUE</code>.</p>
<p>(I don’t know if this is the best/only way to do this - if anybody has suggestions, please let me know!)</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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("gpclib")</span></span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gpclibPermit</span>()</span>
<span id="cb5-3">ca_points <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fortify</span>(ca_merge, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">region =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GEOID"</span>)</span></code></pre></div></div>
</div>
<p>Now, join the points and the shapefile data.</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">ca_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">left_join</span>(ca_merge<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span>data, ca_points, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</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;">"GEOID"</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;">"id"</span>))</span></code></pre></div></div>
</div>
<p>We can finally plot the shapefile and its data!</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">ca_map <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb7-2">  ca_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb7-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</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_polygon</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> long, </span>
<span id="cb7-5">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> lat, </span>
<span id="cb7-6">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group,</span>
<span id="cb7-7">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> any_link_found),</span>
<span id="cb7-8">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gray"</span>, </span>
<span id="cb7-9">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> .<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_iv</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggtitle</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"COVID-Related Links Found on CA School District Sites"</span>)</span></code></pre></div></div>
</div>
<p>To make a nicer looking map, then you can use <code>coord_map()</code>.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">map_projected <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ca_map <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_map</span>()</span>
<span id="cb8-3"></span>
<span id="cb8-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(map_projected)</span></code></pre></div></div>
</div>
<p><img src="https://ivelasq.rbind.io/blog/leaidr-shapefiles/test_map.png" class="img-fluid" alt="Map of California school districts showing whether or not they contained COVID-related links on their website"></p>
<p>Tada! A full school district map for California.</p>
</section>
<section id="call-for-collaboration" class="level2">
<h2 class="anchored" data-anchor-id="call-for-collaboration">Call for collaboration</h2>
<p>Please try out {leaidr}! I hope that it is useful to you in your work. I’d love any collaborators to join me in making it easier/better!</p>
<ul>
<li><strong>Other functionality</strong>: For example: being able to filter shapefiles by NCES IDs as well as states; adding commonly used data (like district demographics).</li>
<li><strong>Issues</strong>: If you run into any issues, please post on the <a href="https://github.com/ivelasq/leaidr/issues">GitHub page!</a></li>
</ul>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ul>
<li><a href="http://www.nickeubank.com/wp-content/uploads/2015/10/RGIS2_MergingSpatialData_part1_Joins.html"><strong>Joining Spatial Data</strong></a></li>
<li><a href="https://rpubs.com/DanielSLee/censusMap"><strong>Analyzing U.S. Census Data Using R</strong></a></li>
</ul>
<center>
<em>Liked this post? I’d love for you to retweet!</em>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Ever wish you could easily create U.S. school district maps 🗺🏫 in <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a>? Check out {leaidr}, which downloads the shapefile from GitHub using <a href="https://twitter.com/rOpenSci?ref_src=twsrc%5Etfw"><span class="citation" data-cites="rOpenSci">@rOpenSci</span></a> 's {piggyback} 🐷! Would love any thoughts on how to improve! Repo: <a href="https://t.co/yOszd4agYM">https://t.co/yOszd4agYM</a> Tutorial: <a href="https://t.co/JuqGQcVR7Z">https://t.co/JuqGQcVR7Z</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1259831120364888066?ref_src=twsrc%5Etfw">May 11, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>reference</category>
  <guid>https://ivelasq.rbind.io/blog/leaidr-shapefiles/</guid>
  <pubDate>Sun, 03 May 2020 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/leaidr-shapefiles/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>You CRAN do it</title>
  <dc:creator>Isabella Velásquez</dc:creator>
  <link>https://ivelasq.rbind.io/blog/you-cran-do-it/</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ivelasq.rbind.io/blog/you-cran-do-it/thumbnail-wide.jpg" class="img-fluid figure-img" alt="Rosie the Riveter with a red spotted bandana and a blue shirt holding her arm"></p>
<figcaption>J. Howard Miller, We Can Do It!</figcaption>
</figure>
</div>
<p>As the @<a href="https://twitter.com/WeAreRLadies">WeAreRLadies</a> curator, I <a href="https://twitter.com/WeAreRLadies/status/1227937968117043200">asked the Twitterverse</a> for advice when submitting a package to the Comprehensive R Archive Network (CRAN) for the first time. Many people replied and offer their tips, experience, and well wishes. I have summarized everybody’s replies below. THANK YOU all for participating!</p>
<p>Here’s what to expect when succeeding to get your package on CRAN!</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
As someone who hopes to submit their first package 📦to CRAN this year… what should I know? 😳
</p>
— We are R-Ladies (<span class="citation" data-cites="WeAreRLadies">@WeAreRLadies</span>) <a href="https://twitter.com/WeAreRLadies/status/1227937968117043200?ref_src=twsrc%5Etfw">February 13, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
<section id="read-the-official-cran-documentation" class="level2">
<h2 class="anchored" data-anchor-id="read-the-official-cran-documentation">Read the official CRAN documentation</h2>
<p>… which is <a href="https://cran.r-project.org/doc/manuals/r-release/R-exts.html">Writing R Extensions</a>! “Necessary and sufficient,” according to Avraham Adler.</p>
</section>
<section id="you-can-get-by-with-a-little-help-from-your-friends" class="level2">
<h2 class="anchored" data-anchor-id="you-can-get-by-with-a-little-help-from-your-friends">You can get by with a little help from your friends</h2>
<p>{usethis}, {devtools}, and {roxygen2}, although not necessary, are useful tools for creating CRAN-ready packages.</p>
</section>
<section id="documentation-is-key" class="level2">
<h2 class="anchored" data-anchor-id="documentation-is-key">Documentation is key</h2>
<ul>
<li>Have tests and coverage via {covr}, and make sure they run without issues on all platforms</li>
<li>CRAN will ask that you add examples to your package, wrapped in <code>\dontrun{}</code> and <code>\donttest{}</code>.</li>
<li>Ask others read your stuff and provide feedback!</li>
</ul>
</section>
<section id="let-reviewers-know-why-this-should-be-on-cran" class="level2">
<h2 class="anchored" data-anchor-id="let-reviewers-know-why-this-should-be-on-cran">Let reviewers know why this should be on CRAN</h2>
<p>A quick note letting the reviewers know why your package should be on CRAN goes a long way.</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Reviewer asking “why do we need this on CRAN?” isn’t a rejection, just respond politely with a reason. <br><br>Also, if <a href="https://t.co/9Mgm9C20E6">https://t.co/9Mgm9C20E6</a> can make it to CRAN, your package belongs there too!
</p>
— Jay Qi (<span class="citation" data-cites="jayyqi">@jayyqi</span>) <a href="https://twitter.com/jayyqi/status/1228049523806617601?ref_src=twsrc%5Etfw">February 13, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
</section>
<section id="be-patient" class="level2">
<h2 class="anchored" data-anchor-id="be-patient">Be patient</h2>
<p>The people at CRAN are busy! It might take a while for them to reply and accept your package. If you want to track the progress of your package, you can take a look at the <a href="https://lockedata.github.io/cransays/articles/dashboard.html">CRAN Incoming Dashboard</a>.</p>
</section>
<section id="emails-will-be-terse" class="level2">
<h2 class="anchored" data-anchor-id="emails-will-be-terse">Emails will be terse</h2>
<p>This is particularly difficult for me to hear, as someone who provides! ample! exclamation marks! in emails! in order to sound cheery and polite, but responses can be short and to-the-point. Breathe, and address everything mentioned. When you do reply, respond to the CRAN list.</p>
</section>
<section id="persist" class="level2">
<h2 class="anchored" data-anchor-id="persist">Persist</h2>
<p>The reviewers will let you know what you need to do for approval. Go through their list carefully and try again!</p>
<center>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Don’t get discouraged if you don’t succeed on your first try. Everyone (including me, my team, and R core) gets rejected from time to time. It sucks, but don’t give up — just make the requested changes and resubmit.
</p>
— Hadley Wickham (<span class="citation" data-cites="hadleywickham">@hadleywickham</span>) <a href="https://twitter.com/hadleywickham/status/1228043230601777152?ref_src=twsrc%5Etfw">February 13, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
<p>Many thanks to the R Community for their words of advice and encouragement ❤</p>
</section>
<section id="guides" class="level2">
<h2 class="anchored" data-anchor-id="guides">Guides</h2>
<ul>
<li><a href="https://cran.r-project.org/doc/manuals/r-release/R-exts.html">Writing R Extensions</a> (Official CRAN Documentation)</li>
<li>Hadley Wickham and Jenny Bryan’s <a href="https://r-pkgs.org/">R Packages</a></li>
<li>Julia Silge’s <a href="https://juliasilge.com/blog/how-i-stopped/">How I Learned to Stop Worrying and Love R CMD Check</a></li>
<li>Maëlle Salmon’s <a href="https://blog.r-hub.io/2020/01/27/examples/">Code Examples in R Package Manuals</a></li>
<li>R-hub’s <a href="https://r-hub.github.io/rhub/articles/rhub.html#prepare-a-cran-submission">Prepare a CRAN submission</a></li>
<li>R-hub’s <a href="https://vimeo.com/329059890">CRAN submission preparation with rhub</a></li>
<li>Karl Broman’s <a href="https://kbroman.org/pkg_primer/pages/cran.html">Getting Your R Package on CRAN</a></li>
<li>Colin Fay’s <a href="https://github.com/ThinkR-open/prepare-for-cran">Preparing your package for a CRAN submission</a></li>
<li>Jp Marín Díaz’s <a href="https://jpmarindiaz.com/2020-01-08-how-to-publish-a-package-to-cran/">How to publish a package to CRAN</a> and <a href="https://jpmarindiaz.com/2020-02-13-from-0-to-cran-in-1-day/">From 0 to CRAN in 1 day</a></li>
<li>Jim Hester’s <a href="https://www.jimhester.com/post/2019-05-01-submit-vroom/">Submitting vroom to CRAN, LIVE!</a></li>
<li>Ryo Nakagawara’s <a href="https://ryo-n7.github.io/2019-09-06-tvthemes-CRAN-announcement/#cran-trials-and-errors-and-future-releases">CRAN Trial(s) and Error(s) and Future Releases</a></li>
</ul>
<center>
<p><em>Liked this article? I’d love for you to retweet!</em></p>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
📢 New blogpost 📢 You CRAN Do It: What CRAN First-Timers Should Know 💪a summary of a thread from <a href="https://twitter.com/WeAreRLadies?ref_src=twsrc%5Etfw"><span class="citation" data-cites="WeAreRLadies">@WeAreRLadies</span></a>. Thank you for all your advice and encouragement! <a href="https://t.co/BimejGvqdr">https://t.co/BimejGvqdr</a> <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> <a href="https://t.co/0Ygk7qHc76">pic.twitter.com/0Ygk7qHc76</a>
</p>
— Isabella Velásquez (<span class="citation" data-cites="ivelasq3">@ivelasq3</span>) <a href="https://twitter.com/ivelasq3/status/1233031919551401984?ref_src=twsrc%5Etfw">February 27, 2020</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>


</section>

 ]]></description>
  <category>how-to</category>
  <guid>https://ivelasq.rbind.io/blog/you-cran-do-it/</guid>
  <pubDate>Tue, 25 Feb 2020 00:00:00 GMT</pubDate>
  <media:content url="https://ivelasq.rbind.io/blog/you-cran-do-it/thumbnail.png" medium="image" type="image/png" height="124" width="144"/>
</item>
</channel>
</rss>
