<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://andybeet.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://andybeet.com/" rel="alternate" type="text/html" /><updated>2026-04-06T16:11:53+00:00</updated><id>https://andybeet.com/feed.xml</id><title type="html">Andy Beet</title><subtitle>Research Scientist and Analyst</subtitle><author><name>Andy Beet</name></author><entry><title type="html">Air: Formatting R code</title><link href="https://andybeet.com/posts/2025/07/air_formatting/" rel="alternate" type="text/html" title="Air: Formatting R code" /><published>2025-07-15T00:00:00+00:00</published><updated>2025-07-15T00:00:00+00:00</updated><id>https://andybeet.com/posts/2025/07/air_formatting</id><content type="html" xml:base="https://andybeet.com/posts/2025/07/air_formatting/"><![CDATA[<p>Have you been thinking that you should probably start using a style guide? No, i don’t mean a fashion guru! I mean following a guide to help maintain code formatted similarly across all functions and scripts. Consistent white space, consistent indentations in conditional statements and for loops. Code formatted exactly the same way ALL the time?</p>

<p>In R, this is pretty easy to do and it involves the use of the tool <a href="https://tidyverse.org/blog/2025/02/air/"><code class="language-plaintext highlighter-rouge">Air</code></a> created by the Posit folks. Described as “an extremely fast R formatter” it will format your code every time you hit save. Best used in conjunction with the <a href="https://style.tidyverse.org/">tidyverse style guide</a></p>

<p>As of the time of writing: auto formatting is ONLY applied to <code class="language-plaintext highlighter-rouge">.r</code>, <code class="language-plaintext highlighter-rouge">.R</code> files. R chunks inside R-Markdown files (‘rmd`) are not formatted.</p>

<p>Note: Air is a <a href="https://posit-dev.github.io/air/formatter.html"><em>layout</em> formatter</a>, “ensuring that whitespace, newlines, and other punctuation conform to a set of rules and standards”</p>

<h3 id="reformatting-existing-code">Reformatting existing code</h3>

<p>Using this tool you can reformat ALL existing code in a repo. From the terminal simply type the command <code class="language-plaintext highlighter-rouge">air format .</code>. Or if you’d prefer you can open every R file and hit save. I know which one i’ll choose!</p>

<h3 id="reformatting-all-future-code">Reformatting all future code</h3>

<p>The easiest way to keep the repo formatted consistently is to include an <code class="language-plaintext highlighter-rouge">air.toml</code> file in the root directory of your repo. The file can remain empty, or you can add specific formatting you’d like in your repo. If left empty <code class="language-plaintext highlighter-rouge">air</code> will apply defaults settings. This is often a good option.</p>

<p>The benefit of using this <code class="language-plaintext highlighter-rouge">air.toml</code> file is that anyone who contributes to your repo will automatically have their contributed code formatted as dictated by the <code class="language-plaintext highlighter-rouge">toml</code> file, rather than any specific user level settings. A no worry solution for consistent formatting of code. The only caveat is that contributors will need to have air installed too, but having the <code class="language-plaintext highlighter-rouge">air.toml</code> in the repo and indicating that air formatting is required by using a <a href="/posts/2025/06/github_templates/">pull request template</a>, for example, this should be painless.</p>

<h3 id="reformatting-code-using-github-actions">Reformatting code using GitHub Actions</h3>

<p>If you want to take things to the next level, you can create a GitHub action to run on all pull requests. The action will check for formatting inconsistencies and fail if formatting is required. If this is of interest see the <a href="https://posit-dev.github.io/air/integration-github-actions.html"><code class="language-plaintext highlighter-rouge">air</code></a> documentation</p>

<p>Now all you need to worry about is coding styles, a subject we’ll talk about at a later date.</p>]]></content><author><name>Andy Beet</name></author><category term="R" /><category term="GitHub" /><category term="git" /><summary type="html"><![CDATA[Have you been thinking that you should probably start using a style guide? No, i don’t mean a fashion guru! I mean following a guide to help maintain code formatted similarly across all functions and scripts. Consistent white space, consistent indentations in conditional statements and for loops. Code formatted exactly the same way ALL the time?]]></summary></entry><entry><title type="html">Using GitHub templates</title><link href="https://andybeet.com/posts/2025/06/github_templates/" rel="alternate" type="text/html" title="Using GitHub templates" /><published>2025-06-15T00:00:00+00:00</published><updated>2025-06-15T00:00:00+00:00</updated><id>https://andybeet.com/posts/2025/06/github_templates</id><content type="html" xml:base="https://andybeet.com/posts/2025/06/github_templates/"><![CDATA[<p>Maintaining multiple GitHub repos is rewarding until you’re stuck deciphering a flood of disorganized issues and PRs. Eventually, the lack of standard formatting becomes a major bottleneck for any productive workflow. You’d like to see a consistent format for all issues and pull requests! Templates are what you have been looking for!</p>

<p>Issue and Pull Request (PR) templates act as a structured “handshake” between a project maintainer and a contributor. Without them, communication often becomes a messy back-and-forth of “Which version are you using?” or “What does this code actually do?” etc.</p>

<p>Here are a few reasons why they are great for collaborative teams:</p>

<h3 id="thoughtful-submission">Thoughtful submission</h3>

<p>Templates act as a checklist that forces contributors to think through their submission.</p>

<p>For Issues: Instead of a report saying “It’s broken,” a template requires a Minimal Reproducible Example (<a href="/posts/2024/01/reprex/">Reprex</a>), environment details (like your R version or OS), and clear steps to recreate the bug.</p>

<p>For Pull Requests: It ensures the author explains the “Why” behind a change, not just the “What.”</p>

<h3 id="reduces-review-fatigue">Reduces “Review Fatigue”</h3>

<p>Reviewing code is mentally taxing. Templates reduce this “cognitive load” by:</p>

<p>Standardizing Layout: When every PR looks the same, reviewers know exactly where to find the testing instructions, the link to the Jira/GitHub issue, and the “breaking changes” warning.</p>

<h3 id="informative-for-new-contributors">Informative for new contributors</h3>

<p>For someone new to your project, the “New Issue” button can be intimidating.</p>

<p>Templates provide scaffolding. They tell the user exactly what information is valued, making them feel more confident that their contribution will be accepted.</p>

<p>It serves as a subtle way to enforce Contribution Guidelines without making someone read a 2,000-word CONTRIBUTING.md file first.</p>

<h3 id="better-historical-records">Better historical records</h3>

<p>Six months from now, when you’re wondering why a specific line of code was changed, a well-filled PR template provides the context that a single-line commit message often misses. It captures the intent and the testing process used at the time.</p>

<h2 id="how-to-implement-templates">How to implement templates</h2>

<p>In GitHub, templates can be written in either markdown or yaml files and are saved in standard locations</p>

<ul>
  <li>.github/ISSUE_TEMPLATE - for issues templates</li>
  <li>.github/PULL_REQUEST_TEMPLATE - for PR templates</li>
</ul>

<p>You can list as many issue templates as you like, for example for issues you could include templates for</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Bug Reporting</code></li>
  <li><code class="language-plaintext highlighter-rouge">Feature Requests</code></li>
  <li><code class="language-plaintext highlighter-rouge">Data Issues</code></li>
</ul>

<h3 id="caveat-pull-request">Caveat: Pull request</h3>

<p>There is a caveat worth mentioning with pull requests templates. If you’d like a default template to appear EVERY time you make a pull request then you must have a default template called <code class="language-plaintext highlighter-rouge">pull_request_template.md</code> residing in the <code class="language-plaintext highlighter-rouge">.github</code> folder.</p>

<p>If you want to include more than this default template you will need to include additional templates to the <code class="language-plaintext highlighter-rouge">PULL_REQUEST_TEMPLATE</code> folder. You will NOT be prompted by GitHub as to which one you want to use. If you have a default that will be used. And, as of date of publication, GitHub does not provide a drop down to select a pull request template. To access the templates in the <code class="language-plaintext highlighter-rouge">PULL_REQUEST_TEMPLATE</code> folder you need to add a snippet of additional text to the URL - <code class="language-plaintext highlighter-rouge">?template=your_template_name.md</code>.</p>

<h2 id="examples">Examples</h2>

<p>To see some examples from across the web</p>

<ul>
  <li>Pull request examples from <a href="https://github.com/axolo-co/pull_request_template">axolo-co</a></li>
  <li>Pull request examples from <a href="https://github.com/devspace/awesome-github-templates?tab=readme-ov-file#rocket-templates-for-pull-requests">devspace</a></li>
  <li>The <a href="https://github.com/NOAA-EDAB/stocksmart">stocksmart</a> R package has examples of both <a href="https://github.com/NOAA-EDAB/stocksmart/tree/main/.github/ISSUE_TEMPLATE">issue</a> and <a href="(https://github.com/NOAA-EDAB/stocksmart/blob/main/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md)">pull request</a> templates</li>
</ul>

<p>And if you want to go one step further … you can create repository templates. These can be set up to contain all of the above templates, a CONTRIBUTING file, CODE_OF_CONDUCT, LICENSE, auto formatting etc. and whenever a repo is created all of these files are bundled with the creation! Pretty cool!</p>

<p>In summary, templates are easy to create, human readable, easy to implement, and have been proven to reduce hair loss!</p>

<p>Enjoy!</p>]]></content><author><name>Andy Beet</name></author><category term="GitHub" /><category term="markdown" /><summary type="html"><![CDATA[Maintaining multiple GitHub repos is rewarding until you’re stuck deciphering a flood of disorganized issues and PRs. Eventually, the lack of standard formatting becomes a major bottleneck for any productive workflow. You’d like to see a consistent format for all issues and pull requests! Templates are what you have been looking for!]]></summary></entry><entry><title type="html">Pulling data from ERDDAP™</title><link href="https://andybeet.com/posts/2025/05/pull_from_erddap/" rel="alternate" type="text/html" title="Pulling data from ERDDAP™" /><published>2025-05-15T00:00:00+00:00</published><updated>2025-05-15T00:00:00+00:00</updated><id>https://andybeet.com/posts/2025/05/accessing_erddap</id><content type="html" xml:base="https://andybeet.com/posts/2025/05/pull_from_erddap/"><![CDATA[<p>Many publicly available scientific datasets from around the world can be found on servers supported by ERDDAP™ (Environmental Research Division’s Data Access Program). Many organizations, like government agencies and universities, run their own ERDDAP™ servers and host oceanographic and environmental datasets.</p>

<p>The data are served up in a consistent way, allowing users to visualize and download data in various standard data formats, like netCDF (nc), csv, txt, JSON.</p>

<p>While it is perfectly reasonable to interact with these ERDDAP™ servers through a web interface, and often preferable initially to identify data sources, read metadata, and visualize the data, pulling and working with the data is often best accomplished using a language like python or R. Since i mostly use R for my work, we’ll go that route.</p>

<p>For R users there is a wonderful package called <a href="https://docs.ropensci.org/rerddap/"><code class="language-plaintext highlighter-rouge">rerddap</code></a> designed to help search, connect, and download data from ERDDAP™ servers. Lets go through an example to demonstrate how to get started. The steps involved are</p>

<ul>
  <li>List all servers (<code class="language-plaintext highlighter-rouge">rerddap::servers()</code>)</li>
  <li>List all datasets on a specific server (<code class="language-plaintext highlighter-rouge">rerddap::ed_datasets()</code>)</li>
  <li>Select and explore dataset fields (<code class="language-plaintext highlighter-rouge">rerddap::info()</code>)</li>
  <li>Pull data (<code class="language-plaintext highlighter-rouge">rerddap::tabledap()</code> or <code class="language-plaintext highlighter-rouge">rerddap::griddap()</code>)</li>
</ul>

<h2 id="list-servers">List servers</h2>

<p>First, let’s see the list of server names available using the <code class="language-plaintext highlighter-rouge">servers()</code> function</p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rerddap</span><span class="o">::</span><span class="n">servers</span><span class="p">()</span><span class="w">
</span><span class="c1">#&gt; # A tibble: 63 × 4</span><span class="w">
</span><span class="c1">#&gt;    name                                                  short_name url   public</span><span class="w">
</span><span class="c1">#&gt;    &lt;chr&gt;                                                 &lt;chr&gt;      &lt;chr&gt; &lt;lgl&gt; </span><span class="w">
</span><span class="c1">#&gt;  1 Voice of the Ocean                                    VOTO       http… TRUE  </span><span class="w">
</span><span class="c1">#&gt;  2 St. Lawrence Global Observatory - CIOOS | Observatoi… SLGO-OGSL  http… TRUE  </span><span class="w">
</span><span class="c1">#&gt;  3 CoastWatch West Coast Node                            CSWC       http… TRUE  </span><span class="w">
</span><span class="c1">#&gt;  4 ERDDAP at the Asia-Pacific Data-Research Center       APDRC      http… TRUE  </span><span class="w">
</span><span class="c1">#&gt;  5 NOAA's National Centers for Environmental Informatio… NCEI       http… TRUE  </span><span class="w">
</span><span class="c1">#&gt;  6 Biological and Chemical Oceanography Data Management… BCODMO     http… TRUE  </span><span class="w">
</span><span class="c1">#&gt;  7 European Marine Observation and Data Network (EMODne… EMODnet    http… TRUE  </span><span class="w">
</span><span class="c1">#&gt;  8 European Marine Observation and Data Network (EMODne… EMODnet P… http… TRUE  </span><span class="w">
</span><span class="c1">#&gt;  9 Marine Institute - Ireland                            MII        http… TRUE  </span><span class="w">
</span><span class="c1">#&gt; 10 CoastWatch Caribbean/Gulf of Mexico Node              CSCGOM     http… TRUE  </span><span class="w">
</span><span class="c1">#&gt; # ℹ 53 more rows</span><span class="w">
</span></code></pre></div></div>

<p><sup>Created on 2025-12-08 with <a href="https://reprex.tidyverse.org">reprex v2.1.1</a></sup></p>

<h2 id="list-datasets">List datasets</h2>

<p>The “CoastWatch West Coast Node” server looks interesting, lets explore that. We’ll need to grab the <code class="language-plaintext highlighter-rouge">url</code> field to explore the datasets hosted on this server.</p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">servers</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">rerddap</span><span class="o">::</span><span class="n">servers</span><span class="p">()</span><span class="w">
</span><span class="n">servers</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">filter</span><span class="p">(</span><span class="n">short_name</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s2">"CSWC"</span><span class="p">)</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">select</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="w">
</span><span class="c1">#&gt; # A tibble: 1 × 1</span><span class="w">
</span><span class="c1">#&gt;   url                                     </span><span class="w">
</span><span class="c1">#&gt;   &lt;chr&gt;                                   </span><span class="w">
</span><span class="c1">#&gt; 1 https://coastwatch.pfeg.noaa.gov/erddap/</span><span class="w">
</span></code></pre></div></div>

<p><sup>Created on 2025-12-08 with <a href="https://reprex.tidyverse.org">reprex v2.1.1</a></sup></p>

<p>Now, at this point you can either copy this url into your browser and explore the contents of the server from there, or you can use <code class="language-plaintext highlighter-rouge">rerddap</code> to list the data sets. At this point we should mention that there are often two types of data hosted on these servers</p>

<ul>
  <li>Gridded data, termed <code class="language-plaintext highlighter-rouge">griddap</code>, in NetCDF (nc) format</li>
  <li>Tabular data, termed <code class="language-plaintext highlighter-rouge">tabledap</code>, often in csv format</li>
</ul>

<p>Let’s search for all of the tabular data on this server.</p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">servers</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">rerddap</span><span class="o">::</span><span class="n">servers</span><span class="p">()</span><span class="w">
</span><span class="n">url</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">servers</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">filter</span><span class="p">(</span><span class="n">short_name</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s2">"CSWC"</span><span class="p">)</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">select</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="w">
  
</span><span class="n">rerddap</span><span class="o">::</span><span class="n">ed_datasets</span><span class="p">(</span><span class="n">which</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tabledap"</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">url</span><span class="p">)</span><span class="w">
</span><span class="c1">#&gt; # A tibble: 293 × 17</span><span class="w">
</span><span class="c1">#&gt;    griddap Subset     tabledap Make.A.Graph wms   files Accessible Title Summary</span><span class="w">
</span><span class="c1">#&gt;    &lt;chr&gt;   &lt;chr&gt;      &lt;chr&gt;    &lt;chr&gt;        &lt;chr&gt; &lt;chr&gt; &lt;chr&gt;      &lt;chr&gt; &lt;chr&gt;  </span><span class="w">
</span><span class="c1">#&gt;  1 ""      https://c… https:/… https://coa… ""    ""    public     * Th… "This …</span><span class="w">
</span><span class="c1">#&gt;  2 ""      https://c… https:/… https://coa… ""    "htt… public     Audi… "Audio…</span><span class="w">
</span><span class="c1">#&gt;  3 ""      https://c… https:/… https://coa… ""    "htt… public     CalC… "Hydro…</span><span class="w">
</span><span class="c1">#&gt;  4 ""      https://c… https:/… https://coa… ""    "htt… public     CalC… "Sampl…</span><span class="w">
</span><span class="c1">#&gt;  5 ""      https://c… https:/… https://coa… ""    "htt… public     CalC… "Cruis…</span><span class="w">
</span><span class="c1">#&gt;  6 ""      https://c… https:/… https://coa… ""    "htt… public     CalC… "Fish …</span><span class="w">
</span><span class="c1">#&gt;  7 ""      https://c… https:/… https://coa… ""    "htt… public     CalC… "Egg m…</span><span class="w">
</span><span class="c1">#&gt;  8 ""      https://c… https:/… https://coa… ""    "htt… public     CalC… "Fish …</span><span class="w">
</span><span class="c1">#&gt;  9 ""      https://c… https:/… https://coa… ""    "htt… public     CalC… "Size …</span><span class="w">
</span><span class="c1">#&gt; 10 ""      https://c… https:/… https://coa… ""    "htt… public     CalC… "Devel…</span><span class="w">
</span><span class="c1">#&gt; # ℹ 283 more rows</span><span class="w">
</span><span class="c1">#&gt; # ℹ 8 more variables: FGDC &lt;chr&gt;, ISO.19115 &lt;chr&gt;, Info &lt;chr&gt;,</span><span class="w">
</span><span class="c1">#&gt; #   Background.Info &lt;chr&gt;, RSS &lt;chr&gt;, Email &lt;chr&gt;, Institution &lt;chr&gt;,</span><span class="w">
</span><span class="c1">#&gt; #   Dataset.ID &lt;chr&gt;</span><span class="w">
</span></code></pre></div></div>

<p><sup>Created on 2025-12-08 with <a href="https://reprex.tidyverse.org">reprex v2.1.1</a></sup></p>

<p>We can see that there are 293 datasets available, each with its own url field (<code class="language-plaintext highlighter-rouge">tabldap</code>) and ID (<code class="language-plaintext highlighter-rouge">Dataset.ID</code>) and other accompanying metadata. As mentioned earlier it may be easier to look at these from within a web browser. But for the sake of this example let’s just look at the <code class="language-plaintext highlighter-rouge">Summary</code>  metadata</p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">servers</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">rerddap</span><span class="o">::</span><span class="n">servers</span><span class="p">()</span><span class="w">
</span><span class="n">url</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">servers</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">filter</span><span class="p">(</span><span class="n">short_name</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s2">"CSWC"</span><span class="p">)</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">select</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="w">
</span><span class="n">datasets</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">rerddap</span><span class="o">::</span><span class="n">ed_datasets</span><span class="p">(</span><span class="n">which</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tabledap"</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">url</span><span class="p">)</span><span class="w">
</span><span class="n">datasets</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">select</span><span class="p">(</span><span class="n">Dataset.ID</span><span class="p">,</span><span class="n">Summary</span><span class="p">)</span><span class="w">
</span><span class="c1">#&gt; # A tibble: 293 × 2</span><span class="w">
</span><span class="c1">#&gt;    Dataset.ID           Summary                                                 </span><span class="w">
</span><span class="c1">#&gt;    &lt;chr&gt;                &lt;chr&gt;                                                   </span><span class="w">
</span><span class="c1">#&gt;  1 allDatasets          "This dataset is a table which has a row of information…</span><span class="w">
</span><span class="c1">#&gt;  2 testTableWav         "Audio data from a local source.\n\ncdm_data_type = Oth…</span><span class="w">
</span><span class="c1">#&gt;  3 erdCalCOFINOAAhydros "Hydrographic data collected by CTD as part of CalCOFI …</span><span class="w">
</span><span class="c1">#&gt;  4 erdCalCOFIcufes      "Samples collected using the Continuous Underway Fish-E…</span><span class="w">
</span><span class="c1">#&gt;  5 erdCalCOFIcruises    "Cruises using one or more ships conducted as part of t…</span><span class="w">
</span><span class="c1">#&gt;  6 erdCalCOFIeggcnt     "Fish egg counts and standardized counts for eggs captu…</span><span class="w">
</span><span class="c1">#&gt;  7 erdCalCOFIeggstg     "Egg morphological developmental stage for eggs of sele…</span><span class="w">
</span><span class="c1">#&gt;  8 erdCalCOFIlrvcnt     "Fish larvae counts and standardized counts for eggs ca…</span><span class="w">
</span><span class="c1">#&gt;  9 erdCalCOFIlrvsiz     "Size data for selected larval fish captured in CalCOFI…</span><span class="w">
</span><span class="c1">#&gt; 10 erdCalCOFIlrvstg     "Developmental stages (yolk sac, preflexion, flexion, p…</span><span class="w">
</span><span class="c1">#&gt; # ℹ 283 more rows</span><span class="w">
</span></code></pre></div></div>

<p><sup>Created on 2025-12-08 with <a href="https://reprex.tidyverse.org">reprex v2.1.1</a></sup></p>

<h2 id="explore-dataset">Explore dataset</h2>

<p>Now, from experience i know there is a dataset hosted here containing data from the <a href="https://www.ndbc.noaa.gov/">National Data Buoy Center</a> (NDBC). The data has a <code class="language-plaintext highlighter-rouge">Dataset.ID</code> = “cwwcNDBCMet”.</p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">datasets</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">filter</span><span class="p">(</span><span class="n">grepl</span><span class="p">(</span><span class="s2">"NDBC"</span><span class="p">,</span><span class="n">Summary</span><span class="p">))</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> 
  </span><span class="n">dplyr</span><span class="o">::</span><span class="n">pull</span><span class="p">(</span><span class="n">Dataset.ID</span><span class="p">)</span><span class="w">
  
</span><span class="p">[</span><span class="m">1</span><span class="p">]</span><span class="w"> </span><span class="s2">"cwwcNDBCMet"</span><span class="w">  
</span></code></pre></div></div>
<p>Once we have this id, we are ready to explore and pull the data. So lets grab all of the information relating to this dataset. We’ll use the function <a href="https://docs.ropensci.org/rerddap/reference/info.html"><code class="language-plaintext highlighter-rouge">info()</code></a></p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">data_info</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">rerddap</span><span class="o">::</span><span class="n">info</span><span class="p">(</span><span class="n">datasetid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"cwwcNDBCMet"</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"https://coastwatch.pfeg.noaa.gov/erddap/"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">data_info</code> is a list object containing metadata, like the url of the server, variables describing the variable names, variable type, and variable data range. This list object is what you’ll pass to the function, <code class="language-plaintext highlighter-rouge">tabledap()</code> to pull the data.</p>

<h2 id="pull-the-dataset">Pull the dataset</h2>

<p>Even though we have identified the data set we want, we don’t really know how much data there is! If you tried to pull all of the data at once, there is a good chance your computer will crash! So in prep, we can explore the set of available variables using a couple of methods that involve the <code class="language-plaintext highlighter-rouge">data_info</code> list object:</p>

<ul>
  <li>
    <p><a href="https://upwell.pfeg.noaa.gov/erddap/info/cwwcNDBCMet/index.html"><code class="language-plaintext highlighter-rouge">rerddap::browse(data_info)</code></a> - will open a webpage on ERDDAP™ describing the data set</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">data_info$variables</code> will list the variables available and <code class="language-plaintext highlighter-rouge">data_info$alldata[[variableName]]</code> will show more detailed information about each variable.</p>
  </li>
</ul>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">erddap_url</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="s1">'https://coastwatch.pfeg.noaa.gov/erddap/'</span><span class="w">
</span><span class="n">datasetid</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="s2">"cwwcNDBCMet"</span><span class="w">
</span><span class="n">data_info</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">suppressMessages</span><span class="p">(</span><span class="n">rerddap</span><span class="o">::</span><span class="n">info</span><span class="p">(</span><span class="n">datasetid</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">erddap_url</span><span class="p">))</span><span class="w">
</span><span class="n">data_info</span><span class="o">$</span><span class="n">variables</span><span class="w">
</span><span class="c1">#&gt;    variable_name data_type           actual_range</span><span class="w">
</span><span class="c1">#&gt; 1            apd     float              0.0, 95.0</span><span class="w">
</span><span class="c1">#&gt; 2           atmp     float           -153.4, 50.0</span><span class="w">
</span><span class="c1">#&gt; 3            bar     float          800.7, 1198.8</span><span class="w">
</span><span class="c1">#&gt; 4           dewp     float            -99.9, 48.7</span><span class="w">
</span><span class="c1">#&gt; 5            dpd     float              0.0, 64.0</span><span class="w">
</span><span class="c1">#&gt; 6            gst     float              0.0, 75.5</span><span class="w">
</span><span class="c1">#&gt; 7       latitude     float          -55.0, 71.758</span><span class="w">
</span><span class="c1">#&gt; 8      longitude     float       -177.75, 179.001</span><span class="w">
</span><span class="c1">#&gt; 9            mwd     short                 0, 359</span><span class="w">
</span><span class="c1">#&gt; 10          ptdy     float            -13.1, 14.9</span><span class="w">
</span><span class="c1">#&gt; 11       station    String                       </span><span class="w">
</span><span class="c1">#&gt; 12          tide     float            -9.37, 6.15</span><span class="w">
</span><span class="c1">#&gt; 13          time    double 4910400.0, 1.7697828E9</span><span class="w">
</span><span class="c1">#&gt; 14           vis     float              0.0, 66.7</span><span class="w">
</span><span class="c1">#&gt; 15            wd     short                 0, 359</span><span class="w">
</span><span class="c1">#&gt; 16          wspd     float              0.0, 96.0</span><span class="w">
</span><span class="c1">#&gt; 17          wspu     float            -98.7, 97.5</span><span class="w">
</span><span class="c1">#&gt; 18          wspv     float            -98.7, 97.5</span><span class="w">
</span><span class="c1">#&gt; 19          wtmp     float            -98.7, 50.0</span><span class="w">
</span><span class="c1">#&gt; 20          wvht     float             0.0, 92.39</span><span class="w">
</span></code></pre></div></div>

<p><sup>Created on 2026-01-30 with <a href="https://reprex.tidyverse.org">reprex v2.1.1</a></sup></p>

<p>What jumps out here is the <code class="language-plaintext highlighter-rouge">station</code> variable and the <code class="language-plaintext highlighter-rouge">latitude</code> and <code class="language-plaintext highlighter-rouge">longitude</code> variables. We’ll now use these to pull the list of stations available</p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">erddap_url</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="s1">'https://coastwatch.pfeg.noaa.gov/erddap/'</span><span class="w">
</span><span class="n">datasetid</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="s2">"cwwcNDBCMet"</span><span class="w">
</span><span class="n">data_info</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">suppressMessages</span><span class="p">(</span><span class="n">rerddap</span><span class="o">::</span><span class="n">info</span><span class="p">(</span><span class="n">datasetid</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">erddap_url</span><span class="p">))</span><span class="w">

</span><span class="n">rerddap</span><span class="o">::</span><span class="n">tabledap</span><span class="p">(</span><span class="w">
  </span><span class="n">data_info</span><span class="p">,</span><span class="w">
  </span><span class="n">fields</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="s2">"station"</span><span class="p">,</span><span class="w"> </span><span class="s2">"longitude"</span><span class="p">,</span><span class="w"> </span><span class="s2">"latitude"</span><span class="p">),</span><span class="w">
  </span><span class="n">distinct</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="w">
</span><span class="p">)</span><span class="w">
</span><span class="c1">#&gt; info() output passed to x; setting base url to: https://coastwatch.pfeg.noaa.gov/erddap</span><span class="w">
</span><span class="c1">#&gt; &lt;ERDDAP tabledap&gt; cwwcNDBCMet</span><span class="w">
</span><span class="c1">#&gt; # A tibble: 1,329 × 3</span><span class="w">
</span><span class="c1">#&gt;    station longitude latitude</span><span class="w">
</span><span class="c1">#&gt;    &lt;chr&gt;       &lt;dbl&gt;    &lt;dbl&gt;</span><span class="w">
</span><span class="c1">#&gt;  1 0Y2W3       -87.3    44.8 </span><span class="w">
</span><span class="c1">#&gt;  2 18CI3       -86.9    41.7 </span><span class="w">
</span><span class="c1">#&gt;  3 20CM4       -86.5    42.1 </span><span class="w">
</span><span class="c1">#&gt;  4 23020        38.5    22.2 </span><span class="w">
</span><span class="c1">#&gt;  5 31201       -48.1   -27.7 </span><span class="w">
</span><span class="c1">#&gt;  6 32012       -85.4   -19.6 </span><span class="w">
</span><span class="c1">#&gt;  7 32301      -105.     -9.9 </span><span class="w">
</span><span class="c1">#&gt;  8 32302       -85.1   -18   </span><span class="w">
</span><span class="c1">#&gt;  9 32487       -77.7     3.52</span><span class="w">
</span><span class="c1">#&gt; 10 32488       -77.5     6.26</span><span class="w">
</span><span class="c1">#&gt; # ℹ 1,319 more rows</span><span class="w">
</span></code></pre></div></div>

<p><sup>Created on 2026-01-30 with <a href="https://reprex.tidyverse.org">reprex v2.1.1</a></sup></p>

<p>Now that you have identified the set of buoy stations available you can now either pull individual stations data or pull a collection of stations within a geographic region. Either of these tasks will require using the <code class="language-plaintext highlighter-rouge">erddap::tabledap()</code> function. For example:</p>

<h3 id="get-data-from-a-single-station">Get data from a single station</h3>

<p>Select the station(s) of interest, then get the data. In this example we’ll pull all of the data associated with buoy <code class="language-plaintext highlighter-rouge">32012</code></p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">erddap_url</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="s1">'https://coastwatch.pfeg.noaa.gov/erddap/'</span><span class="w">
</span><span class="n">datasetid</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="s2">"cwwcNDBCMet"</span><span class="w">
</span><span class="n">data_info</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">suppressMessages</span><span class="p">(</span><span class="n">rerddap</span><span class="o">::</span><span class="n">info</span><span class="p">(</span><span class="n">datasetid</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">erddap_url</span><span class="p">))</span><span class="w">

</span><span class="n">variables</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">data_info</span><span class="o">$</span><span class="n">variables</span><span class="o">$</span><span class="n">variable_name</span><span class="w">

</span><span class="n">rerddap</span><span class="o">::</span><span class="n">tabledap</span><span class="p">(</span><span class="w">
  </span><span class="n">datasetid</span><span class="p">,</span><span class="w">
  </span><span class="n">fields</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">variables</span><span class="p">,</span><span class="w">
  </span><span class="n">query</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">paste0</span><span class="p">(</span><span class="s1">'station="'</span><span class="p">,</span><span class="w"> </span><span class="m">32012</span><span class="p">,</span><span class="w"> </span><span class="s1">'"'</span><span class="p">)</span><span class="w">
</span><span class="p">)</span><span class="w">
</span><span class="c1">#&gt; &lt;ERDDAP tabledap&gt; cwwcNDBCMet</span><span class="w">
</span><span class="c1">#&gt;    File size:    [9.37 mb]</span><span class="w">
</span><span class="c1">#&gt; # A tibble: 84,918 × 20</span><span class="w">
</span><span class="c1">#&gt;      apd  atmp   bar  dewp   dpd   gst latitude longitude   mwd  ptdy station</span><span class="w">
</span><span class="c1">#&gt;    &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt;    &lt;dbl&gt;     &lt;dbl&gt; &lt;int&gt; &lt;dbl&gt;   &lt;int&gt;</span><span class="w">
</span><span class="c1">#&gt;  1  6.88   NaN   NaN   NaN  13.8   NaN    -19.6     -85.4   215   NaN   32012</span><span class="w">
</span><span class="c1">#&gt;  2  7.01   NaN   NaN   NaN  13.8   NaN    -19.6     -85.4   253   NaN   32012</span><span class="w">
</span><span class="c1">#&gt;  3  6.8    NaN   NaN   NaN  11.4   NaN    -19.6     -85.4   202   NaN   32012</span><span class="w">
</span><span class="c1">#&gt;  4  7.31   NaN   NaN   NaN  11.4   NaN    -19.6     -85.4   200   NaN   32012</span><span class="w">
</span><span class="c1">#&gt;  5  7.32   NaN   NaN   NaN  10.8   NaN    -19.6     -85.4   190   NaN   32012</span><span class="w">
</span><span class="c1">#&gt;  6  7.09   NaN   NaN   NaN  11.4   NaN    -19.6     -85.4   204   NaN   32012</span><span class="w">
</span><span class="c1">#&gt;  7  7.68   NaN   NaN   NaN  10.8   NaN    -19.6     -85.4   207   NaN   32012</span><span class="w">
</span><span class="c1">#&gt;  8  7.07   NaN   NaN   NaN  12.9   NaN    -19.6     -85.4   235   NaN   32012</span><span class="w">
</span><span class="c1">#&gt;  9  7.09   NaN   NaN   NaN  11.4   NaN    -19.6     -85.4   219   NaN   32012</span><span class="w">
</span><span class="c1">#&gt; 10  6.94   NaN   NaN   NaN  10     NaN    -19.6     -85.4   201   NaN   32012</span><span class="w">
</span><span class="c1">#&gt; # ℹ 84,908 more rows</span><span class="w">
</span><span class="c1">#&gt; # ℹ 9 more variables: tide &lt;dbl&gt;, time &lt;dttm&gt;, vis &lt;dbl&gt;, wd &lt;int&gt;, wspd &lt;dbl&gt;,</span><span class="w">
</span><span class="c1">#&gt; #   wspu &lt;dbl&gt;, wspv &lt;dbl&gt;, wtmp &lt;dbl&gt;, wvht &lt;dbl&gt;</span><span class="w">
</span></code></pre></div></div>

<p><sup>Created on 2026-01-30 with <a href="https://reprex.tidyverse.org">reprex v2.1.1</a></sup></p>

<p>Now you can work with this data in R for whatever purpose you’d like.</p>

<h3 id="get-data-by-geographic-region">Get data by geographic region</h3>

<p>If you want to simply pull all of the buoys in a specific region you can do this too. ERDDAP™ has a few server side functions that let you narrow your search. For example, lets pull all stations within a region along the Northeast USA seaboard, (around Cape cod, MA) between latitudes [41.6,41.8] and longitudes [-70.5, -69.5]</p>

<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">erddap_url</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="s1">'https://coastwatch.pfeg.noaa.gov/erddap/'</span><span class="w">
</span><span class="n">datasetid</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="s2">"cwwcNDBCMet"</span><span class="w">
</span><span class="n">data_info</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">suppressMessages</span><span class="p">(</span><span class="n">rerddap</span><span class="o">::</span><span class="n">info</span><span class="p">(</span><span class="n">datasetid</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">erddap_url</span><span class="p">))</span><span class="w">

</span><span class="n">variables</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">data_info</span><span class="o">$</span><span class="n">variables</span><span class="o">$</span><span class="n">variable_name</span><span class="w">

</span><span class="n">rerddap</span><span class="o">::</span><span class="n">tabledap</span><span class="p">(</span><span class="w">
  </span><span class="n">datasetid</span><span class="p">,</span><span class="w">
  </span><span class="n">fields</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">variables</span><span class="p">,</span><span class="w">
  </span><span class="s1">'latitude&gt;=41.6'</span><span class="p">,</span><span class="s1">'latitude&lt;=41.8'</span><span class="p">,</span><span class="s1">'longitude&lt;=-69.5'</span><span class="p">,</span><span class="s1">'longitude&gt;=-70.5'</span><span class="w">
</span><span class="p">)</span><span class="w">
</span><span class="c1">#&gt; &lt;ERDDAP tabledap&gt; cwwcNDBCMet</span><span class="w">
</span><span class="c1">#&gt;    Path: [C:\Users\ANDREW~1.BEE\AppData\Local\Temp\RtmpSQAjbB\R\rerddap\c9f6726fc0a4f89d39c0c92913fabd90.csv]</span><span class="w">
</span><span class="c1">#&gt;    Last updated: [2026-01-30 11:00:00.736641]</span><span class="w">
</span><span class="c1">#&gt;    File size:    [54.57 mb]</span><span class="w">
</span><span class="c1">#&gt; # A tibble: 501,476 × 20</span><span class="w">
</span><span class="c1">#&gt;      apd  atmp   bar  dewp   dpd   gst latitude longitude   mwd  ptdy station</span><span class="w">
</span><span class="c1">#&gt;    &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt;    &lt;dbl&gt;     &lt;dbl&gt; &lt;int&gt; &lt;dbl&gt; &lt;chr&gt;  </span><span class="w">
</span><span class="c1">#&gt;  1   NaN   4.9  998.   NaN   NaN   9.8     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt;  2   NaN   4.9  998.   NaN   NaN  11.9     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt;  3   NaN   4.9  998    NaN   NaN  11.3     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt;  4   NaN   4.9  998    NaN   NaN  10.8     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt;  5   NaN   5    998.   NaN   NaN  10       41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt;  6   NaN   5    998.   NaN   NaN  11.4     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt;  7   NaN   5.1  998.   NaN   NaN   9.9     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt;  8   NaN   5    998.   NaN   NaN  11.6     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt;  9   NaN   5    998.   NaN   NaN   8.9     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt; 10   NaN   4.9  998.   NaN   NaN  10.6     41.7     -70.0    NA   NaN CHTM3  </span><span class="w">
</span><span class="c1">#&gt; # ℹ 501,466 more rows</span><span class="w">
</span><span class="c1">#&gt; # ℹ 9 more variables: tide &lt;dbl&gt;, time &lt;dttm&gt;, vis &lt;dbl&gt;, wd &lt;int&gt;, wspd &lt;dbl&gt;,</span><span class="w">
</span><span class="c1">#&gt; #   wspu &lt;dbl&gt;, wspv &lt;dbl&gt;, wtmp &lt;dbl&gt;, wvht &lt;dbl&gt;</span><span class="w">
</span></code></pre></div></div>

<p><sup>Created on 2026-01-30 with <a href="https://reprex.tidyverse.org">reprex v2.1.1</a></sup></p>

<p>From this narrow geographic region there is only one station <code class="language-plaintext highlighter-rouge">CHMT3</code> which is a buoy off Chatham, MA</p>

<h2 id="summary">Summary</h2>

<p>Getting the data from ERDDAP™ into R requires a little work. You can use a combination of the R package <code class="language-plaintext highlighter-rouge">rerddap</code> and the ERDDAP™ website to help identify the data you are interested in.</p>

<p>Fortunately for the buoy station data used in the example, there is an R package called <a href="https://noaa-edab.github.io/buoydata/"><code class="language-plaintext highlighter-rouge">buoydata</code></a> available to help with the <a href="https://noaa-edab.github.io/buoydata/articles/buoymap.html">identification</a> of buoy station availability with tools to pull station data hassle free.</p>

<p>Enjoy exploring the masses of data on ERDDAP™</p>]]></content><author><name>Andy Beet</name></author><category term="R" /><summary type="html"><![CDATA[Many publicly available scientific datasets from around the world can be found on servers supported by ERDDAP™ (Environmental Research Division’s Data Access Program). Many organizations, like government agencies and universities, run their own ERDDAP™ servers and host oceanographic and environmental datasets.]]></summary></entry><entry><title type="html">Go get an ORCID iD!</title><link href="https://andybeet.com/posts/2025/03/orcid_ids/" rel="alternate" type="text/html" title="Go get an ORCID iD!" /><published>2025-03-15T00:00:00+00:00</published><updated>2025-03-15T00:00:00+00:00</updated><id>https://andybeet.com/posts/2025/03/orcid_ids</id><content type="html" xml:base="https://andybeet.com/posts/2025/03/orcid_ids/"><![CDATA[<p>What is an ORCID iD? Should you get one? What can you do with it? If you are a researcher or a scholar it might be worth you signing up for one. Here’s why …</p>

<h2 id="what-is-an-orcid">What is an ORCID?</h2>

<p>An Open Researcher and Contributor ID (<a href="https://info.orcid.org/what-is-orcid/">ORCID</a>) is a 16 digit, persistent, name independent unique identifier. From ORCID site “ founded specifically to help solve the problem of name ambiguity in research and to enable transparent and trustworthy connections between researchers, their contributions, and their affiliations.”</p>

<p>So even if you change names or affiliations your ORCID remains the same and “follows” you through your career. Read more about ORCID from the <a href="https://orcid.org/">official site</a>.</p>

<p>And … It is <a href="https://info.orcid.org/researchers/">free</a> to obtain</p>

<h2 id="whats-it-used-for">What’s it used for?</h2>

<p>Many publishers and institutions are using ORCID to seamlessly share information between data systems, so the next article you submit for publication, expect to see a field asking for it! Outside of publishers, you can use it in your R package development and link your software development skills to your scientific publishing.</p>

<p>Simply, add to the DESCRIPTION file of you R package and, if you use <a href="https://pkgdown.r-lib.org/"><code class="language-plaintext highlighter-rouge">pkgdown</code></a>, which you should :index_pointing_at_the_viewer:, it will propagate to the online documentation. For example:</p>

<p>Simply by by adding this snippet of code, (of course, you’ll have your own 16 digit code when you sign up!)</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Authors@R: 
    person(given = "Andy",family = "Beet", role = c("aut", "cre"),
           email = "andrew.beet@noaa.gov",
           comment = c(ORCID = "0000-0001-8270-7090"))
</code></pre></div></div>

<p>… results in <code class="language-plaintext highlighter-rouge">pkgdown</code> displaying hyperlinked icons, <img src="/images/posts/ORCID-iD_icon_24x24.png" alt="icon" />, in two locations, the home page and the citation page, displaying something like this:</p>

<p><img src="/images/posts/orcid2.png" alt="citation page" /></p>

<p>For more info on the benefits of using <code class="language-plaintext highlighter-rouge">pkgdown</code> to showcase your R package, you might find the post on <a href="/posts/2025/02/enhancing_rpackages/">Enhancing R packages</a> useful.</p>

<p>So go on, get yourself an ORCID iD!!</p>]]></content><author><name>Andy Beet</name></author><category term="R" /><category term="workflows" /><summary type="html"><![CDATA[What is an ORCID iD? Should you get one? What can you do with it? If you are a researcher or a scholar it might be worth you signing up for one. Here’s why …]]></summary></entry><entry><title type="html">Enhancing an R package</title><link href="https://andybeet.com/posts/2025/02/enhancing_rpackages/" rel="alternate" type="text/html" title="Enhancing an R package" /><published>2025-02-15T00:00:00+00:00</published><updated>2025-02-15T00:00:00+00:00</updated><id>https://andybeet.com/posts/2025/02/enhancing_rpackages</id><content type="html" xml:base="https://andybeet.com/posts/2025/02/enhancing_rpackages/"><![CDATA[<p>So you want to create an R package? Well there are a ton of resources available to help with this, the best being the official book from the Posit folks, <a href="https://r-pkgs.org/">R Packages (2e)</a>. However, after the initial set up, organization, and implementation of the package there are several other related components you should think about including to make it function, look, and feel polished!</p>

<p>You can see ALL of the components mentioned in this post implemented in the R package <a href="https://noaa-edab.github.io/stocksmart/"><code class="language-plaintext highlighter-rouge">stocksmart</code></a></p>

<h2 id="well-start-with-some-cosmetic-enhancemnents">We’ll start with some cosmetic enhancemnents</h2>

<h3 id="add-a-hex">Add a Hex</h3>

<p>You’ve seen these. Many site have these cool looking hexes, the Posit team has one for every R package in the <a href="https://tidyverse.org/">tidyverse</a>! Good news is that they are easy to create and implement.</p>

<p>The package <a href="https://github.com/GuangchuangYu/hexSticker">hexSticker</a> is a good start to help create a hex! Simply save your design as <code class="language-plaintext highlighter-rouge">logo.png</code>, add it to your <code class="language-plaintext highlighter-rouge">man/figures</code> folder, and link to it from your <code class="language-plaintext highlighter-rouge">README.md</code> with an image tag defined after the name of your package. Something like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># package_name &lt;img src="man/figures/logo.png" align="right" width="120" /&gt;
</code></pre></div></div>

<h3 id="create-a-pkgdown-site">Create a pkgdown site</h3>

<p>If you’d like others to use your package, then having a nice looking website with documentation is essential. A step made very easy using a combination of the <a href="https://pkgdown.r-lib.org/"><code class="language-plaintext highlighter-rouge">pkgdown</code></a> and the <a href="https://usethis.r-lib.org/"><code class="language-plaintext highlighter-rouge">usethis</code></a> packages.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">pkgdown</code> will create the website locally from a single function call, <code class="language-plaintext highlighter-rouge">build_site()</code>. The default layout is pretty good right out of the box, but you can customize a little if you’d like.</li>
  <li><code class="language-plaintext highlighter-rouge">usethis</code> will create a GitHub action (with the functions <code class="language-plaintext highlighter-rouge">use_github_action()</code> or <code class="language-plaintext highlighter-rouge">use_pkgdown_github_pages()</code>) to redeploy your website everytime you make changes to the code or documentation</li>
</ul>

<p>Not only will a website make your package more user friendly, it will highlight your documentation and show you where you need to focus more attention. A previous post on <a href="/posts/2024/05/githubactions1/">GitHub actions</a> for R packages explain this in more detail.</p>

<h3 id="add-user-guides">Add user guides</h3>

<p>Adding a helpful user guide or several articles to introduce a user to your package can enhance the adoption of your package by others. They are also pretty easy to create! If you know <code class="language-plaintext highlighter-rouge">Rmarkdown</code> or <code class="language-plaintext highlighter-rouge">quarto</code> then it’s a breeze. Just save your <code class="language-plaintext highlighter-rouge">rmd</code> or <code class="language-plaintext highlighter-rouge">qmd</code> in the <code class="language-plaintext highlighter-rouge">vignettes</code> folder of your package and <code class="language-plaintext highlighter-rouge">pkgdown</code> will take care of integrating them to your site.</p>

<h3 id="custom-issue-templates">Custom issue templates</h3>

<p>Now i’m sure your package is awesome!! But some users may want some additional features that you didn’t anticipate, or maybe they found a bug in your code! I know, very unlikely right? :rofl: The standard issue templates provided by GitHub work just fine as a reporting tool, but to avoid a lot of back and forth conversation with a user of you package you can <a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository">customize templates</a> to ask for exactly the information you need from a user to either troubleshoot a bug or add a feature.</p>

<p>These custom templates are written in <a href="https://learnxinyminutes.com/yaml/">YAML</a>, formatted ASCII text. They are saved in the folder <code class="language-plaintext highlighter-rouge">.github/ISSUE_TEMPLATE</code></p>

<h3 id="contibuting-guidelines-and-code-of-coduct">Contibuting guidelines and code of coduct</h3>

<p>Adding a guide with instructions on how users can contribute to your package is worthwhile if you want to avoid potential future headaches! Although this does depend on whether people actually read the guidelines, which often they don’t! This then begs the question, why bother? Well the answer is, you can point people to the document when needed without having to waste time explaining the process each time. The same applies to a <a href="https://www.jessesquires.com/blog/2020/01/24/github-default-community-health-files/">code of conduct</a> document, outlining what you expect from contributors regarding behaviour and the type of environment you want to foster.</p>

<p>Best practices often suggest to add these two documents as markdown, <code class="language-plaintext highlighter-rouge">.md</code>, files in the root of your repository with names <code class="language-plaintext highlighter-rouge">CODE_OF_CONDUCT.md</code> and <code class="language-plaintext highlighter-rouge">CONTRIBUTING.md</code>. A great template, to get you started, can be found at <a href="https://github.com/jessesquires/.github">@jessesquires</a>.</p>

<p>Oh, once again <code class="language-plaintext highlighter-rouge">pkgdown</code> will take care of integrating them into your site automatically!</p>

<h2 id="enhancements-to-make-your-package-more-robust">Enhancements to make your package more robust</h2>

<h3 id="r-cmd-checks-continuous-integration">R-CMD checks: Continuous integration</h3>

<p>One of the most painful debugging experiences you might encounter is when someone informs you that your package wont install on their OS! What do you do? You work on a Windows machine and a MacOS user just informed you they are having issues installing your package! Well the answer is to use <a href="/posts/2024/05/githubactions1/">GitHub actions</a>. Like the <code class="language-plaintext highlighter-rouge">pkgdown</code> example above, you can create, very easily, a workflow that will, for every pushed commit or pull request, run a series of checks (analogous to those required when submitting to CRAN) to inform you, amongst other things, if your package can be installed without issues on a variety of operating systems!</p>

<p>Again, the <code class="language-plaintext highlighter-rouge">usethis</code> package has a function, <code class="language-plaintext highlighter-rouge">use_github_action("check-standard")</code>, that will create the appropriate workflow YAML for you. This workflow is analogous to the <code class="language-plaintext highlighter-rouge">devtools::check()</code> function you can run locally which checks your package using “all known best practices”</p>

<h3 id="unit-tests">Unit tests</h3>

<p>Probably one of the least utilized practices in package deployment! Not because unit tests are hard to implement but because it can be hard to think about what kinds of test you need/should implement.</p>

<p>Well, the Posit folks help with the implementation part of unit testing with the <a href="https://testthat.r-lib.org/"><code class="language-plaintext highlighter-rouge">testthat</code></a> package. This package has tools to aid in file structure set up, and includes many tools to aid in different types of tests. And if you’ve implemented the R-CMD continuous integration workflow (described above) then all of the tests you create will be run when you push a commit or make a pull request!</p>

<p>These tests are pretty important, if thought about carefully, since they should catch many bugs BEFORE you release your package. And if you add new features or change the some of the functionality, these tests should aid in determining if the expected outputs are reasonable and that you haven’t introduced unexpected bugs.</p>

<h3 id="releases">Releases</h3>

<p>Versioning your package should be taken very seriously. Reproducibility is so important in todays age of rapidly changing software. If you don’t version your software, your future self and others will find it extremely difficult to reproduce old code. In addition it should be used to communicate changes, like bug fixes or new features to users and other developers.</p>

<p>For details regarding when and how to version your package, see <a href="/posts/2025/01/rpackage_versioning/">versioning R packages</a>.</p>

<h2 id="summary">Summary</h2>

<p>You can see ALL of the components mentioned in this post implemented in the R package <a href="https://noaa-edab.github.io/stocksmart/"><code class="language-plaintext highlighter-rouge">stocksmart</code></a></p>]]></content><author><name>Andy Beet</name></author><category term="R" /><category term="workflows" /><category term="GitHub" /><category term="versioning" /><summary type="html"><![CDATA[So you want to create an R package? Well there are a ton of resources available to help with this, the best being the official book from the Posit folks, R Packages (2e). However, after the initial set up, organization, and implementation of the package there are several other related components you should think about including to make it function, look, and feel polished!]]></summary></entry><entry><title type="html">Versioning R packages</title><link href="https://andybeet.com/posts/2025/01/rpackage_versioning/" rel="alternate" type="text/html" title="Versioning R packages" /><published>2025-01-15T00:00:00+00:00</published><updated>2025-01-15T00:00:00+00:00</updated><id>https://andybeet.com/posts/2025/01/versioning_rpackages</id><content type="html" xml:base="https://andybeet.com/posts/2025/01/rpackage_versioning/"><![CDATA[<p>You’ve reached the point in which you want to officially start to version your R package. How do you go about doing this? When should you version? How often? What versioning scheme should you use? How do you document the changes?</p>

<p>All great questions! :rofl: Lets talk this through …</p>

<p>So in principle, every time content is pushed to the <code class="language-plaintext highlighter-rouge">main</code> branch of your R package repository should trigger a versioning/release event. This statement assumes that you are using best practices and have adopted a branching strategy. This earlier post on selecting a <a href="/posts/2024/07/maindevfeature/">branching strategy</a> is worth a read if you are unsure of what this means.</p>

<p>Under the branching strategy i like to employ, called feature branching, all new features and bug fixes reside on their own branch until completion. At that point they are pulled into the development branch, often named <code class="language-plaintext highlighter-rouge">dev</code>, via a pull request. At this point multiple workflows are run to check various aspects of the code, typically R-CMD checks. Check out the post on <a href="/posts/2025/02/enhancing_rpackages/">enhancing your R packages</a> for more info on this.</p>

<p>If all checks pass, then the development branch is ready to be pulled in to the main branch. If they fail, you’ll need to address the issues and fix them. Better you do it now vs a user submitting an issue at a later date.</p>

<p>When all checks pass you need to update the package version in the DESCRIPTION file and update content in the NEWS.md file to summarize all relevant changes to the package, whether a feature enhancement, a bug fix, or something else.</p>

<p>After you then, merge the pull request from <code class="language-plaintext highlighter-rouge">dev</code> -&gt; <code class="language-plaintext highlighter-rouge">main</code> you immediately release the package using the release feature on GitHub. The description of the release should use the information in the NEWS.md file and the release version should match the version number in the DESCRIPTION file. The target commit associated with this release should be the latest commit to the <code class="language-plaintext highlighter-rouge">main</code> branch.</p>

<p>So this covers the how, when, and what? But what about the questions relating to how often should a package be released or what versioning scheme should be used?</p>

<p>The versioning scheme that is considered best practice is <a href="https://semver.org/">semantic versioning</a>. An earlier post, <a href="/posts/2024/12/semantic_versioning/">Versioning R packages</a>, goes into more detail on how this relates to R package development.</p>

<p>And with regard to how often you should release, well that depends on a lot of things, how frequently bugs are found and addressed or how quickly you want to add new features. Of course these do not need to be versioned as independent events. You can bundle new features and bug fixes into the same release of your package. You just need to adjust the version number to reflect these changes and document the changes in the NEWS.md file, often termed the changelog.</p>

<h2 id="summary">Summary</h2>

<p>Under this workflow, at any point in time the <code class="language-plaintext highlighter-rouge">main</code> branch of the repository should represent a working released version of your package. If someone came across your repository and installed your package, it should be expected to work just fine! All developmental work, whether new features or bug fixes, should reside on their own branches and only merged into the <code class="language-plaintext highlighter-rouge">main</code> branch when fully tested and ready for release! This way the main branch remains “clean” of issues.</p>

<p>Hope this helps!</p>]]></content><author><name>Andy Beet</name></author><category term="R" /><category term="workflows" /><category term="GitHub" /><category term="versioning" /><summary type="html"><![CDATA[You’ve reached the point in which you want to officially start to version your R package. How do you go about doing this? When should you version? How often? What versioning scheme should you use? How do you document the changes?]]></summary></entry><entry><title type="html">Semantic versioning</title><link href="https://andybeet.com/posts/2024/12/semantic_versioning/" rel="alternate" type="text/html" title="Semantic versioning" /><published>2024-12-01T00:00:00+00:00</published><updated>2024-12-01T00:00:00+00:00</updated><id>https://andybeet.com/posts/2024/12/semantic_vesioning</id><content type="html" xml:base="https://andybeet.com/posts/2024/12/semantic_versioning/"><![CDATA[<p>The official site for <a href="https://semver.org/">Semantic versioning</a> is available in many languages indicating, in part, how important this subject is across the world for software development. It provides a clear, standardized way to communicate the nature of changes between releases, which helps manage dependencies and predict the impact of updates. By using a version format like MAJOR.MINOR.PATCH, developers indicate whether an update is a backwards-incompatible breaking change (MAJOR), a new backwards-compatible feature (MINOR), or a backwards-compatible bug fix (PATCH).</p>

<p>In the development of R packages it is no different. Let’s dive a little deeper with some examples. Following semantic versioning we adopt the format of MAJOR.MINOR.PATCH. For example v3.5.1. The interpretation of these three components can be a little confusing, especially in the context of R package development.</p>

<ul>
  <li>Changes in the PATCH component refer to small changes, like bug fixes. It is assumed that these changes do NOT break any existing code. They are “backward compatible”. Nothing changes in the package except an error has been corrected</li>
  <li>Changes in the MINOR component refer to changes such as new features. These new features integrate with the package, they complement other features already present, and do NOT break existing code.</li>
  <li>Changes in the MAJOR component refer to changes that would break existing code. For example, if a user was using a particular function in your package, and you changed the code in this function that resulted in a different output structure, the users code would break. This would be “backward incompatible”</li>
</ul>

<h2 id="examples">Examples</h2>

<p>Suppose a package is currently at version 3.5.1</p>

<ul>
  <li>If one or more bugs were fixed (PATCH), the next release would be version 3.5.2</li>
  <li>If a new feature was added (MINOR), the next release would be version 3.6.0. (Note, the PATCH is reset to zero. It would not be 3.6.1)</li>
  <li>If a new breaking change was added (MAJOR), the next release would be version 4.0.0. (Note, both MINOR and PATCH are reset to zero)</li>
  <li>If several bugs were fixed (PATCH) and a couple of new features (MINOR), the next release would be version 3.6.0. (Note, default to the higher order change, MINOR)</li>
  <li>If several bugs were fixed (PATCH), a couple of new features added (MINOR), and a restructure of the package (MAJOR), the next release would be version 4.0.0. (Note, default to the higher order change, MAJOR)</li>
</ul>

<p>I think you get it! Enough said.</p>]]></content><author><name>Andy Beet</name></author><category term="R" /><category term="versioning" /><summary type="html"><![CDATA[The official site for Semantic versioning is available in many languages indicating, in part, how important this subject is across the world for software development. It provides a clear, standardized way to communicate the nature of changes between releases, which helps manage dependencies and predict the impact of updates. By using a version format like MAJOR.MINOR.PATCH, developers indicate whether an update is a backwards-incompatible breaking change (MAJOR), a new backwards-compatible feature (MINOR), or a backwards-compatible bug fix (PATCH).]]></summary></entry><entry><title type="html">Automate versioning for R data packages</title><link href="https://andybeet.com/posts/2024/11/rpackage_versioning/" rel="alternate" type="text/html" title="Automate versioning for R data packages" /><published>2024-11-01T00:00:00+00:00</published><updated>2024-11-01T00:00:00+00:00</updated><id>https://andybeet.com/posts/2024/11/automate_versioning</id><content type="html" xml:base="https://andybeet.com/posts/2024/11/rpackage_versioning/"><![CDATA[<p>Do you find yourself downloading data from a server over and over again to make sure you have the latest data?
Then struggle to work out what’s changed from the last time you downloaded it?</p>

<p>If so, why not why not create an R package to version and document the data changes. That way you’ll always be able to go back to an older version and you’ll be able to track what has changed through time.</p>

<p>You can do all of this using a GitHub action. Within the workflow, the steps you’ll need are (not limited to):</p>

<ul>
  <li>A function to connect to the server or API and download the data on a defined schedule</li>
  <li>A function to compare the new data pull with the current data in the package</li>
  <li>An optional step to email yourself a report explaining the differences, if any (using a parameterized Rmd)</li>
  <li>An optional step to update the README.md file to inform the user of the date of the most recent data pull</li>
  <li>A function to update the version number in the DESCRIPTION file</li>
  <li>A function to document the data changes in the NEWS.md file</li>
  <li>Commit all changes to the repo</li>
  <li>Create a new GitHub release using the notes added to the NEWS.md</li>
</ul>

<p>This seems like a lot, and it might take a while to get things set up and working correctly, but the benefits are huge!</p>

<h2 id="example-stocksmart-package">Example: Stocksmart package</h2>

<p>As a real example, consider the R data package <a href="https://noaa-edab.github.io/stocksmart/">stocksmart</a>. This is an R data package that serves up data from all federally managed fish stocks in the USA.
Our group relies on this data to update annual ecosystem reports. Having the data automatically pulled, versioned, and documented saves us a lot of time.</p>

<p>The specifics of this <a href="https://github.com/NOAA-EDAB/stocksmart/blob/main/.github/workflows/stocksmartapi.yml">workflow</a> are:</p>

<ul>
  <li>A <a href="/posts/2024/06/cronjobs/">cron job</a> job to update this data set running on a schedule every Wednesday at noon EST.</li>
  <li>Following <a href="https://semver.org/">semantic versioning</a>, these data changes are considered patch fixes and hence the version number will increment by 0.0.1 each time the data is updated.</li>
  <li>A report is emailed to me after the workflow has finished running outlining the changes seen in the data. This is achieved using the <a href="https://github.com/dawidd6/action-send-mail">Send mail GitHub action</a></li>
  <li>The readme.Rmd and readme.md are updated to add the date of the most recent pull</li>
  <li>The <a href="https://noaa-edab.github.io/stocksmart/news/index.html">NEWS.md</a> and the DESCRIPTION file are updated to outline changes</li>
  <li>All files are committed to the repo</li>
  <li>If changes are found a new release is created using the <a href="https://usethis.r-lib.org/">usethis</a> package. specifically the <code class="language-plaintext highlighter-rouge">use_github_release</code> function.</li>
</ul>

<p>You will need to add <a href="https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets">secrets</a> to your repo to allow for the email action and the GitHub release function to behave as expected. Once set up this workflow is a maintenance light way to always have up-to date data to work with in R, not only for you, but for the R community at large!</p>

<p>Happy coding!</p>]]></content><author><name>Andy Beet</name></author><category term="GitHub" /><category term="workflows" /><category term="R" /><summary type="html"><![CDATA[Do you find yourself downloading data from a server over and over again to make sure you have the latest data? Then struggle to work out what’s changed from the last time you downloaded it?]]></summary></entry><entry><title type="html">Error handling with `tryCatch()`</title><link href="https://andybeet.com/posts/2024/10/trycatch/" rel="alternate" type="text/html" title="Error handling with `tryCatch()`" /><published>2024-10-01T00:00:00+00:00</published><updated>2024-10-01T00:00:00+00:00</updated><id>https://andybeet.com/posts/2024/10/Error_handling</id><content type="html" xml:base="https://andybeet.com/posts/2024/10/trycatch/"><![CDATA[<p>Error handling is not something scientists typically incorporate into their code. However, there a situations in which incorporating such a thing can save you hours of headache!</p>

<p>Some examples:</p>

<ul>
  <li>You want to run a lot of model simulations/fitting in sequence. If one model iteration causes an error then your code stops without finishing</li>
  <li>You are pulling a large amount of data from a server to analyse. Connection to the server is interrupted and your workflow stops.</li>
  <li>Generally, you have a series of steps in workflow. If one of the steps fail, the whole workflow fails.</li>
</ul>

<p>Ideally, you want to be able to handle these situations within your code, adapt to the error, and continue.</p>

<p>In the examples above, solutions might be:</p>

<ul>
  <li>If a model causes an error, write the issue to a file, then simulate a replacement.</li>
  <li>If the server connection is interrupted, and throws an error, try to reconnect, before continuing</li>
</ul>

<p>Using the <code class="language-plaintext highlighter-rouge">tryCatch()</code> function, bundled in base R, is a great option.</p>

<h2 id="example-1-database-connection">Example 1: Database connection</h2>

<p>This example attempts to accesses an oracle server to pull data. 
Custom warnings are returned based on the type of warning thrown</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chan &lt;- tryCatch(
  {
    driver &lt;- ROracle::Oracle()
    chan &lt;- ROracle::dbConnect(driver, dbname=server,username=uid,password=pwd)
  }, warning=function(w) {
    if (grepl("login denied",w)) {message("login to server failed - Check username and password")}
    if (grepl("locked",w)) {message("logon to server failed - Account may be locked")}
    message(paste0("Can not Connect to Database: ",server))
    return(NA)
  }, error=function(e) {
    message(paste0("Terminal error: ",e))
    return(NA)
  }
)

</code></pre></div></div>

<h2 id="example-2-download-a-file-from-a-url">Example 2: Download a file from a url</h2>

<p>Attempt to download a file from an online location. If it’s missing, or can’t be downloaded for some reason, the code skips the file</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># get file, catch error for missing file
result &lt;- tryCatch(
  {
    downloader::download(fpath,destfile=destfile,quiet=TRUE,mode="wb")
    res &lt;- TRUE
  }, error = function(e){
    message(paste0("No data for ",afname))
    return(FALSE)
  },warning = function(w) 
    return(FALSE)
)

if (!result) {
  next
}
</code></pre></div></div>

<p>In summary, error handling can save you a lot of frustration from code breaking prematurely!</p>]]></content><author><name>Andy Beet</name></author><category term="R" /><summary type="html"><![CDATA[Error handling is not something scientists typically incorporate into their code. However, there a situations in which incorporating such a thing can save you hours of headache!]]></summary></entry><entry><title type="html">Add release tags in git</title><link href="https://andybeet.com/posts/2024/08/releasetags/" rel="alternate" type="text/html" title="Add release tags in git" /><published>2024-08-01T00:00:00+00:00</published><updated>2024-08-01T00:00:00+00:00</updated><id>https://andybeet.com/posts/2024/08/add_release_tags</id><content type="html" xml:base="https://andybeet.com/posts/2024/08/releasetags/"><![CDATA[<p>Scenario: You have a repository in which you’ve been using for a while. You use it for your scientific work and have published papers based on it.
However, you never created releases of the repo corresponding to each publication and now you have no way of reproducing the work used in your publications.
What can you do?</p>

<p>Well, you can add release tags to any “old” commit, providing you can identify the commits! 
Now this isn’t a recommended practice or a substitute for not following best practices, but in a pinch it can help out “the younger, inexperienced you of years gone by”.</p>

<p>Turns out it is pretty simple too!</p>

<p>First, identify the commit hash. Second, decide on the tagname you want to assign to this commit. Then, run the <code class="language-plaintext highlighter-rouge">git tag</code> command.</p>

<p>For example, if your hash is <code class="language-plaintext highlighter-rouge">1e4b567712d785bb972665a2edd9401a17d9875d</code> and you want to tag this with the name, <code class="language-plaintext highlighter-rouge">v1.3.1</code> then you’d run the following lines of code in the terminal</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git tag v1.3.1 1e4b567712d785bb972665a2edd9401a17d9875d
git push origin v1.3.1
</code></pre></div></div>

<p>If you want to annotate the release, and store the taggers name, date, time, along with a message you can use the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git tag -a v1.3.1 1e4b567712d785bb972665a2edd9401a17d9875d -m "Version 1.3.1 Release"
git push origin v1.3.1
</code></pre></div></div>

<p>Repeat this as many times as you’d like.</p>

<p>In GitHub you should be able to now create a release using this tag!</p>

<p>Make sure you add good release notes in the description field so you know why you tagged this particular point in time as a release point!</p>]]></content><author><name>Andy Beet</name></author><category term="git" /><category term="GitHub" /><summary type="html"><![CDATA[Scenario: You have a repository in which you’ve been using for a while. You use it for your scientific work and have published papers based on it. However, you never created releases of the repo corresponding to each publication and now you have no way of reproducing the work used in your publications. What can you do?]]></summary></entry></feed>