<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Community on Posit Open Source</title>
    <link>https://posit-open-source.netlify.app/categories/community/</link>
    <description>Recent content in Community on Posit Open Source</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 03 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://posit-open-source.netlify.app/categories/community/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>posit::conf(2025) Quarto talks</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2025-11-24-conf-talk-videos/</link>
      <pubDate>Mon, 24 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2025-11-24-conf-talk-videos/</guid>
      <dc:creator>Andrew Holz</dc:creator><description><![CDATA[<p>The posit::conf(2025) session videos are now live! We&rsquo;ve created a curated playlist highlighting all the talks that showcase Quarto&mdash;how it is evolving, how people are using it, and how they&rsquo;re building on top of it.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?si=RnKN-0bM7C0bwXfQ&amp;list=PLitrm9UndxcvQgAigiiOofTEPAWpROiiK" 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>
<p>Talks included in the playlist, broken up into a few categories for easier browsing, are as follows:</p>
<h1 id="quarto-extensions--advanced-features">Quarto Extensions &amp; Advanced Features
</h1>
<table>
  <thead>
      <tr>
          <th>Speakers</th>
          <th>Title</th>
          <th>Thumbnail</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Carlos Scheidegger (Quarto Team)</strong></td>
          <td>What we&rsquo;re doing to make Quarto fast(er)</td>
          <td><a href="https://youtu.be/OBHppBRztO4" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/OBHppBRztO4/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>Christophe Dervieux (Quarto Team)</strong></td>
          <td>Beyond the Basics: Expanding Quarto&rsquo;s Capabilities</td>
          <td><a href="https://youtu.be/u9ev3mvC-p0" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/u9ev3mvC-p0/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>Garrick Aden-Buie</strong></td>
          <td>Theming Made Easy: Introducing brand.yml</td>
          <td><a href="https://youtu.be/DPaoNM8Ux04" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/DPaoNM8Ux04/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>Gordon Woodhull (Quarto Team)</strong></td>
          <td>Brand YML and Dark Mode in Quarto</td>
          <td><a href="https://youtu.be/WNwsgS-klMA" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/WNwsgS-klMA/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>JooYoung Seo</strong></td>
          <td>maidr: Empowering Accessible, Multimodal Data Science with Quarto</td>
          <td><a href="https://youtu.be/QR7mdgM8Hf0" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/QR7mdgM8Hf0/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
  </tbody>
</table>
<h1 id="workflow-automation--reporting">Workflow Automation &amp; Reporting
</h1>
<table>
  <thead>
      <tr>
          <th>Speakers</th>
          <th>Title</th>
          <th>Thumbnail</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Becca Krouse</strong></td>
          <td>Instant Impact: Developing {docorator} to Simplify Document Production</td>
          <td><a href="https://youtu.be/SWt-lcnYlNM" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/SWt-lcnYlNM/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>John Paul Helveston</strong></td>
          <td>surveydown: A Markdown-Based Platform for Interactive Surveys</td>
          <td><a href="https://youtu.be/VwoeFKNvN5k" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/VwoeFKNvN5k/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>Keaton Wilson</strong></td>
          <td>Using Quarto to Improve Formatting and Automation</td>
          <td><a href="https://youtu.be/vHrI17AeYGs" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/vHrI17AeYGs/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
  </tbody>
</table>
<h1 id="teaching--education">Teaching &amp; Education
</h1>
<table>
  <thead>
      <tr>
          <th>Speakers</th>
          <th>Title</th>
          <th>Thumbnail</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Claus Wilke</strong></td>
          <td>Teaching data visualization with R entirely in Quarto</td>
          <td><a href="https://youtu.be/Q7y0YqCuvHc" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/Q7y0YqCuvHc/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>Mine Çetinkaya-Rundel (Quarto Team)</strong></td>
          <td>Leveraging LLMs for student feedback in introductory data science courses</td>
          <td><a href="https://youtu.be/5gS7AUGwZPs" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/5gS7AUGwZPs/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>Ted Laderas</strong></td>
          <td>Empowering Learners with WebR, Pyodide, and Quarto</td>
          <td><a href="https://youtu.be/EQ9_MP2PYL8" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/EQ9_MP2PYL8/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
  </tbody>
</table>
<h1 id="business-collaboration--publishing">Business, Collaboration &amp; Publishing
</h1>
<table>
  <thead>
      <tr>
          <th>Speakers</th>
          <th>Title</th>
          <th>Thumbnail</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Andrew Heiss</strong> and <strong>Gabe Osterhout</strong></td>
          <td>Election Night Reporting Using R &amp; Quarto</td>
          <td><a href="https://youtu.be/UCloM4GcfVY" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/UCloM4GcfVY/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>Bill Pikounis</strong></td>
          <td>Quarto for Business Collaboration and Technical Documentation in Word docx format</td>
          <td><a href="https://youtu.be/4-dQ2Q985A0" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/4-dQ2Q985A0/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
      <tr>
          <td><strong>Timothy Keyes</strong></td>
          <td>Trust, but Verify: Lessons from Deploying LLMs</td>
          <td><a href="https://youtu.be/HYQaZTLb2Co" target="_blank" rel="noopener"><div class="not-prose"><figure>
    <img class="h-auto max-w-full rounded-lg"
      src="https://img.youtube.com/vi/HYQaZTLb2Co/hqdefault.jpg"
      alt="thumb" 
      loading="lazy"
    >
  </figure></div>
</a>
</td>
      </tr>
  </tbody>
</table>
<div class="callout callout-tip" role="note" aria-label="Tip">
<div class="callout-header">
<span class="callout-title">Tip</span>
</div>
<div class="callout-body">
<p><strong>Workshop materials now available:</strong><br>
The Quarto team has published full materials from the two workshops at posit::conf 2025: &ldquo;Branded Websites, Presentations, Dashboards, and PDFs with Quarto&rdquo; and &ldquo;Extending Quarto&rdquo;.<br>
You can access the workshop websites, exercise source code, and full slide decks under a CC BY-SA 4.0 license from the <a href="https://quarto.org/docs/blog/posts/2025-10-27-conf-workshops-materials/" target="_blank" rel="noopener">Quarto blog</a>
.</p>
</div>
</div>
<p>We hope you enjoyed this look back at the Quarto sessions from posit::conf(2025). Every year the community brings new ideas, new tools, and new ways of working &mdash; and we&rsquo;d love to see <strong>your</strong> voice added to the mix. We hope to see you next year, and maybe even see <em>you</em> up on stage sharing your own work at posit::conf!</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2025-11-24-conf-talk-videos/thumbnail.png" length="221625" type="image/png" />
    </item>
    <item>
      <title>Python Open-Source Developer</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2025/python-open-source-developer/</link>
      <pubDate>Wed, 12 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2025/python-open-source-developer/</guid>
      <dc:creator>Max Kuhn</dc:creator><description><![CDATA[<p>We are hiring a Python open-source developer with a specialization in data analysis and modeling tools. Since deep learning models already have extensive support in Python, our focus is on the analysis and modeling of <em>tabular data</em>. Our primary goal is to develop packages that enhance the existing capabilities of frameworks such as scikit-learn. Note that the current position doesn&rsquo;t involve building or publishing models created here; <em>this is a pure package developer role</em>.</p>
<p>We think that the tidymodels <a href="https://www.tmwr.org/software-modeling#fundamentals-for-modeling-software" target="_blank" rel="noopener">philosophy</a>
 can enhance modeling in Python, and we believe that learning more about modeling in Python will provide us with ideas on how to improve tidymodels. To clarify, we are not creating a tidymodels Python package; however, some of its APIs may be beneficial to Python users. Two examples are <a href="https://recipes.tidymodels.org/" target="_blank" rel="noopener">recipes</a>
 and broom&rsquo;s <a href="https://broom.tidymodels.org/" target="_blank" rel="noopener">tidy and augment</a>
 verbs.</p>
<p>There are numerous ways that individuals can contribute to improving the Python ecosystem. We have a lot of ideas, but we also want to know what our new hire believes is most important. A sample of potential projects that have been on our mind:</p>
<ul>
<li>
<p>Grid search for model tuning has a fairly bad reputation for being inefficient. However, space-filling designs (SFDs) are excellent tools for making small tuning grids that methodically cover the entire parameter space. Users would benefit from having an integrated tool that can create grids from their pipelines using optimal SFDs.</p>
</li>
<li>
<p>There are occasions where we might decline to produce a prediction, perhaps due to our prediction data being extrapolations from the training set. <em>Applicability Domain</em> methods measure extrapolation and can help determine where the model&rsquo;s predictions are likely to be poor. An API that can take a model object and the training set could generate a score that informs users when their predictions are <del>hallucinated</del> unlikely to be accurate.</p>
</li>
<li>
<p>Python deserves an original (Python-only) implementation of the popular <a href="https://scholar.google.com/scholar?hl=en&amp;as_sdt=0%2C7&amp;q=Regularization&#43;Paths&#43;for&#43;Generalized&#43;Linear&#43;Models&#43;via&#43;Coordinate&#43;Descent&amp;btnG=" target="_blank" rel="noopener">glmnet model</a>
. There are Python libraries that wrap the original Fortran code; however, this approach isn&rsquo;t easily supported, nor is it able to facilitate the numerous extensions of this particular model (e.g., <a href="https://scholar.google.com/scholar?hl=en&amp;as_sdt=0%2C7&amp;q=%22A&#43;sparse-group&#43;lasso%22&amp;btnG=" target="_blank" rel="noopener">group-wise penalties</a>
, <a href="https://scholar.google.com/scholar?hl=en&amp;as_sdt=0%2C7&amp;q=%22Nearly&#43;unbiased&#43;variable&#43;selection&#43;under&#43;minimax&#43;concave&#43;penalty%22&amp;btnG=" target="_blank" rel="noopener">MCP</a>
 penalties, etc). This would be a substantial and in-depth project.</p>
</li>
</ul>
<p>We have about a dozen other project ideas.</p>
<p>Open-source developers at Posit often have a broader role than just writing and testing code. We are often the folks defining what is deemed important and prioritizing our work. Additionally, we frequently undertake tasks that are typically considered part of developer relations, such as reaching out to the community, creating additional technical content, speaking at conferences, and teaching workshops. If you are a driven and independent developer, you might be interested in this position. You&rsquo;ll have a lot of agency here and in an environment that encourages quality. Our developers tend to feel a personal stake in our work and want it to be as good as it can be. We&rsquo;re a completely remote team, flexible in terms of how and when we work, and we do a good job of minimizing administrative overhead for engineers.</p>
<p><strong>To learn more about the position and to apply, visit the <a href="https://posit.co/job-detail/?gh_jid=7510613003" target="_blank" rel="noopener">Careers page</a>
.</strong></p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2025/python-open-source-developer/thumbnail-sq.jpg" length="30429" type="image/jpeg" />
    </item>
    <item>
      <title>posit::conf(2025) Quarto workshop materials</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2025-10-27-conf-workshops-materials/</link>
      <pubDate>Mon, 27 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2025-10-27-conf-workshops-materials/</guid>
      <dc:creator>Charlotte Wickham</dc:creator><description><![CDATA[<p>At posit::conf(2025), we were thrilled to offer two comprehensive Quarto workshops designed to help users at different stages of their journey with Quarto. Whether you were looking to create beautifully branded outputs or extend Quarto&rsquo;s functionality with custom solutions, these workshops provided hands-on learning experiences with expert instructors.</p>
<p>All materials from both workshops are available online. You can access the full workshop websites, source code, and exercises to learn at your own pace or adapt them for your own teaching; they are both released with a <a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener">CC BY-SA 4.0</a>
 license.</p>
<h2 id="branded-websites-presentations-dashboards-and-pdfs-with-quarto">Branded Websites, Presentations, Dashboards, and PDFs with Quarto
</h2>
<p><a href="https://posit-conf-2025.github.io/quarto-brand/" class="rounded">Workshop website</a>
<a href="https://github.com/posit-conf-2025/quarto-brand/" class="rounded"><i></i> Source</a>
<a href="https://github.com/posit-dev/quarto-brand-exercises/" class="rounded"><i></i> Exercises</a></p>
<p>Led by <a href="https://ivelasq.rbind.io/" target="_blank" rel="noopener">Isabella Velásquez</a>
, Posit, PBC and <a href="https://www.linkedin.com/in/sarakaltman" target="_blank" rel="noopener">Sara Altman</a>
, Posit, PBC.</p>
<blockquote>
<p>Designed for data scientists, analysts, and content creators, this immersive session will teach you how to craft cohesive reports and presentations while refining your workflow with Quarto&rsquo;s latest features.</p>
<p>You will learn how to create dynamic websites, professional PDF documents, engaging presentations, and interactive dashboards using Quarto. This workshop highlights Quarto&rsquo;s powerful theming capabilities, including the new support for brand.yml, which ensures that your work maintains a professional and cohesive style across all formats.</p>
<p>By the end of the session, you&rsquo;ll be equipped to:</p>
<ul>
<li>Build and deploy Quarto websites.</li>
<li>Generate professional presentations and PDF reports.</li>
<li>Create interactive dashboards for data visualization and reporting.</li>
<li>Use brand.yml to define and apply consistent theming across all outputs.</li>
</ul>
<p>Whether you&rsquo;re looking to enhance your personal projects or streamline organizational outputs, this workshop will equip you with the tools to create polished, professional results.</p>
</blockquote>
<h2 id="extending-quarto">Extending Quarto
</h2>
<p><a href="https://posit-conf-2025.github.io/quarto-extend/" class="rounded">Workshop website</a>
<a href="https://github.com/posit-conf-2025/quarto-extend/" class="rounded"><i></i> Source</a>
<a href="https://github.com/posit-conf-2025/quarto-extend-exercises/" class="rounded"><i></i> Exercises</a></p>
<p>Led by <a href="https://mine-cr.com/" target="_blank" rel="noopener">Mine Çetinkaya-Rundel</a>
, Posit, PBC + Duke University and <a href="https://www.cwick.co.nz/" target="_blank" rel="noopener">Charlotte Wickham</a>
 Posit, PBC.</p>
<blockquote>
<p>In this workshop, we will dive deep into ways of customizing your Quarto
outputs with tooling beyond built-in features. This workshop is designed
for data scientists, analysts, and technical writers looking to extend
Quarto&rsquo;s capabilities to suit their unique workflows better.</p>
<p>Participants will learn how to create custom extensions, including new
formats, templates, and filters, to enhance their document production
process. Through hands-on exercises and real-world examples, you&rsquo;ll gain
practical skills in:</p>
<ul>
<li>Developing and integrating custom formats to support diverse outputs
while reducing repetition across projects.</li>
<li>Substituting Quarto&rsquo;s templates with your own to customize formats
beyond the built-in options.</li>
<li>Implementing filters to automate and streamline content
transformation.</li>
</ul>
<p>By the end of the workshop, you will be able to leverage Quarto&rsquo;s
extensibility to create powerful, tailored solutions for your
documentation needs. Whether you have just worked on a few Quarto
projects or are an everyday user, this workshop will equip you with the
tools and knowledge to take your document workflows to the next level.</p>
</blockquote>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2025-10-27-conf-workshops-materials/thumbnail.png" length="192305" type="image/png" />
    </item>
    <item>
      <title>Tidyverse developer day 2025</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2025/tdd-2025/</link>
      <pubDate>Mon, 21 Jul 2025 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2025/tdd-2025/</guid>
      <dc:creator>Max Kuhn</dc:creator><description><![CDATA[<!--
TODO:
* [ ] Look over / edit the post's title in the yaml
* [ ] Edit (or delete) the description; note this appears in the Twitter card
* [ ] Pick category and tags (see existing with `hugodown::tidy_show_meta()`)
* [ ] Find photo & update yaml metadata
* [ ] Create `thumbnail-sq.jpg`; height and width should be equal
* [ ] Create `thumbnail-wd.jpg`; width should be >5x height
* [ ] `hugodown::use_tidy_thumbnails()`
* [ ] Add intro sentence, e.g. the standard tagline for the package
* [ ] `usethis::use_tidy_thanks()`
-->
<p>The 2025 Tidy Dev Day will be on September 19th! We&rsquo;ll gather after posit::conf near the conference venue (see the link to the event page at the bottom).</p>
<p>Tidy Dev Day (TDD) is an event where developers and open source contributors meet to collaboratively solve issues. You can hone your software engineering skills or work on your first contribution. We will have a slate of existing issues that you can work on with or without the assistance of our developers.</p>
<p>Here&rsquo;s how <a href="https://lacion.rbind.io/post/my-first-user/" target="_blank" rel="noopener">Laura Acion</a>
 described the 2019 event:</p>
<blockquote>
<p>I wish there were more of these R-related dev days. Developing events that are friendly, diverse, and safe to advance not only the tidyverse. I see no downsides. Kudos to the organizers.</p>
</blockquote>
<p>Plus&hellip;</p>
<div style="text-align: center">
<img src="https://posit-open-source.netlify.app/blog/tidyverse/2025/tdd-2025/GONG.jpg" alt="plot of chunk gong" width="70%" />
</div>
<br>
<h2 id="who-should-attend">Who should attend
</h2>
<p>You <strong>don&rsquo;t</strong> have to have an extensive development background or experience solving issues, or making pull requests. You do need a GitHub account, and some git experience.</p>
<p>Leading up to TDD, we will hold (optional) virtual &ldquo;office hours&rdquo; for TDD participants to help you with your Git workflow so that you can stroll into TDD confident that your R, Git, GitHub, and IDE are set up in the most ideal way possible to work in harmony on your laptop.</p>
<h2 id="how-to-sign-up">How to sign up
</h2>
<p>There is a token $10 cost for the day; we provide the venue, snacks, lunch, and a barista. If cost is an issue, please email <a href="mailto:hadley@posit.co">hadley@posit.co</a>
 and we&rsquo;ll work that out. We only charge a small fee to encourage people to show up for the day.</p>
<p><a href="https://lu.ma/mpr5c30q" target="_blank" rel="noopener"><strong>Get your ticket now!</strong></a>
</p>
<p><strong>Note</strong>: by using this link, you agree to Posit&rsquo;s Privacy Policy, available at <a href="https://posit.co/about/privacy-policy/" target="_blank" rel="noopener">https://posit.co/about/privacy-policy/</a>
. You also consent to using <a href="https://lu.ma/" target="_blank" rel="noopener">https://lu.ma/</a>
 for the purposes of processing your event attendance fees.</p>
<p><a href="https://www.tidyverse.org/tags/tidyverse-dev-day/" target="_blank" rel="noopener">Previous Tidy Dev Days</a>
 have sold out quickly, so don&rsquo;t wait!</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2025/tdd-2025/thumbnail-wd.jpg" length="37162" type="image/jpeg" />
    </item>
    <item>
      <title>Learning the tidyverse with the help of AI tools</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2025/learn-tidyverse-ai/</link>
      <pubDate>Fri, 04 Apr 2025 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2025/learn-tidyverse-ai/</guid>
      <dc:creator>Mine Çetinkaya-Rundel</dc:creator><description><![CDATA[<!--
TODO:
* [ ] Look over / edit the post's title in the yaml
* [ ] Edit (or delete) the description; note this appears in the Twitter card
* [ ] Pick category and tags (see existing with [`hugodown::tidy_show_meta()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html))
* [ ] Find photo & update yaml metadata
* [ ] Create `thumbnail-sq.jpg`; height and width should be equal
* [ ] Create `thumbnail-wd.jpg`; width should be >5x height
* [ ] [`hugodown::use_tidy_thumbnails()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html)
* [ ] Add intro sentence, e.g. the standard tagline for the package
* [ ] [`usethis::use_tidy_thanks()`](https://usethis.r-lib.org/reference/use_tidy_thanks.html)
-->
<p>As an educator who teaches data science with R, I have LOTS of opinions about using artificial intelligence (AI) tools when learning R. But I will keep this post to the use of generative AI tools, like ChatGPT, in learning R, and specifically learning to do data science with R and the tidyverse.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>I&rsquo;ll first walk you through three case studies that demonstrate what asking for help from a generative AI tool looks like. Then, I&rsquo;ll wrap up the post with some tips and good practices for getting the most out of help provided by these tools in the context of writing tidyverse code.</p>
<p>Before we get started, though, it&rsquo;s important to note that knowledge bases of Large Language Models (LLMs) that underlie popular generative AI tools are private and lack transparency. There are important societal concerns about the fairness of equitable access to these tools. It&rsquo;s unclear how developers or users of these models can be held accountable. Additionally, there is an environmental impact to using these tools.</p>
<h2 id="case-study-1-reshaping-and-plotting">Case study 1: Reshaping and plotting
</h2>
<p>The first case study features an example on reshaping and plotting the <code>billboard</code> data frame and it&rsquo;s directly out of <a href="https://r4ds.hadley.nz/" target="_blank" rel="noopener">R for Data Science</a>
. In fact, it&rsquo;s <a href="https://r4ds.hadley.nz/data-tidy.html#sec-billboard" target="_blank" rel="noopener">worked out in the book</a>
. Here is the initial prompt:</p>
<blockquote>
<p>Use the billboard dataset in the tidyr package to create a visualization of rank vs. week number for each song in the dataset.</p>
</blockquote>
<p>And the following is what <a href="https://chatgpt.com/" target="_blank" rel="noopener">ChatGPT</a>
 by OpenAI suggests as the first answer:</p>
<blockquote>
<p>The <code>billboard</code> dataset from the tidyr package contains weekly rankings of songs on the Billboard charts. Here&rsquo;s how you can visualize the rank vs. week number for each song in the dataset using R:</p>
</blockquote>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='c'># Load required libraries</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://tidyr.tidyverse.org'>tidyr</a></span><span class='o'>)</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://ggplot2.tidyverse.org'>ggplot2</a></span><span class='o'>)</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://dplyr.tidyverse.org'>dplyr</a></span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Load the billboard dataset</span></span>
<span><span class='nf'><a href='https://rdrr.io/r/utils/data.html'>data</a></span><span class='o'>(</span><span class='s'>"billboard"</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Prepare the data for visualization</span></span>
<span><span class='nv'>billboard_long</span> <span class='o'>&lt;-</span> <span class='nv'>billboard</span> <span class='o'>|&gt;</span></span>
<span>  <span class='nf'><a href='https://tidyr.tidyverse.org/reference/pivot_longer.html'>pivot_longer</a></span><span class='o'>(</span></span>
<span>    cols <span class='o'>=</span> <span class='nf'><a href='https://tidyselect.r-lib.org/reference/starts_with.html'>starts_with</a></span><span class='o'>(</span><span class='s'>"wk"</span><span class='o'>)</span>,</span>
<span>    names_to <span class='o'>=</span> <span class='s'>"week"</span>,</span>
<span>    values_to <span class='o'>=</span> <span class='s'>"rank"</span>,</span>
<span>    names_prefix <span class='o'>=</span> <span class='s'>"wk"</span>,</span>
<span>    values_drop_na <span class='o'>=</span> <span class='kc'>TRUE</span></span>
<span>  <span class='o'>)</span></span>
<span></span>
<span><span class='c'># Convert week to a numeric value</span></span>
<span><span class='nv'>billboard_long</span><span class='o'>$</span><span class='nv'>week</span> <span class='o'>&lt;-</span> <span class='nf'><a href='https://rdrr.io/r/base/numeric.html'>as.numeric</a></span><span class='o'>(</span><span class='nv'>billboard_long</span><span class='o'>$</span><span class='nv'>week</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Create the visualization</span></span>
<span><span class='nf'><a href='https://ggplot2.tidyverse.org/reference/ggplot.html'>ggplot</a></span><span class='o'>(</span><span class='nv'>billboard_long</span>, <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/aes.html'>aes</a></span><span class='o'>(</span>x <span class='o'>=</span> <span class='nv'>week</span>, y <span class='o'>=</span> <span class='nv'>rank</span>, group <span class='o'>=</span> <span class='nv'>track</span>, color <span class='o'>=</span> <span class='nv'>track</span><span class='o'>)</span><span class='o'>)</span> <span class='o'>+</span></span>
<span>  <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/geom_path.html'>geom_line</a></span><span class='o'>(</span>show.legend <span class='o'>=</span> <span class='kc'>FALSE</span>, alpha <span class='o'>=</span> <span class='m'>0.6</span><span class='o'>)</span> <span class='o'>+</span></span>
<span>  <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/scale_continuous.html'>scale_y_reverse</a></span><span class='o'>(</span><span class='o'>)</span> <span class='o'>+</span>  <span class='c'># Reverse the y-axis since rank 1 is the top position</span></span>
<span>  <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/labs.html'>labs</a></span><span class='o'>(</span></span>
<span>    title <span class='o'>=</span> <span class='s'>"Song Rank vs. Week Number"</span>,</span>
<span>    x <span class='o'>=</span> <span class='s'>"Week Number"</span>,</span>
<span>    y <span class='o'>=</span> <span class='s'>"Rank"</span>,</span>
<span>    caption <span class='o'>=</span> <span class='s'>"Data: Billboard (tidyr package)"</span></span>
<span>  <span class='o'>)</span> <span class='o'>+</span></span>
<span>  <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/ggtheme.html'>theme_minimal</a></span><span class='o'>(</span><span class='o'>)</span></span>
</code></pre>
<img src="https://posit-open-source.netlify.app/blog/tidyverse/2025/learn-tidyverse-ai/figs/unnamed-chunk-1-1.png" width="700px" style="display: block; margin: auto;" />
</div>
<p>ChatGPT also provides a neat explanation of the code:</p>
<blockquote>
<p><strong>Explanation</strong></p>
<ol>
<li>Pivoting the Data: The <code>billboard</code> dataset is in wide format, with week columns (<code>wk1</code>, <code>wk2</code>, etc.). We use <a href="https://tidyr.tidyverse.org/reference/pivot_longer.html" target="_blank" rel="noopener"><code>pivot_longer()</code></a>
 to reshape it into a long format with week and rank columns.</li>
<li>Rank vs. Week Plot: Each song&rsquo;s weekly rankings are connected with lines (<a href="https://ggplot2.tidyverse.org/reference/geom_path.html" target="_blank" rel="noopener"><code>geom_line()</code></a>
), and we reverse the y-axis since rank 1 is the best.</li>
<li>Grouping by Track: The group aesthetic ensures lines are drawn separately for each song.</li>
</ol>
<p><strong>Output</strong></p>
<p>This will create a line plot where each line represents a song&rsquo;s rank progression over weeks. The y-axis is reversed to reflect higher rankings at the top.</p>
</blockquote>
<p>There are a few things about this answer that are promising:</p>
<ul>
<li>The response is a tidyverse approach.</li>
<li>It uses <a href="https://tidyr.tidyverse.org/reference/pivot_longer.html" target="_blank" rel="noopener"><code>pivot_longer()</code></a>
 as opposed to the superseded alternative <a href="https://tidyr.tidyverse.org/reference/gather.html" target="_blank" rel="noopener"><code>gather()</code></a>
.</li>
<li>The plot features a reversed y-axis, <a href="https://r4ds.hadley.nz/data-tidy.html#fig-billboard-ranks" target="_blank" rel="noopener">just like in the book</a>
</li>
</ul>
<p>However, the resulting plot doesn&rsquo;t show exactly what the prompt asked for &ndash; the lines are colored by <code>track</code>, which produces a busy plot that is difficult to interpret. While this is not ideal, it&rsquo;s something a new learner can easily spot and ask ChatGPT for a follow up correcting it. For example, a subsequent prompt like the following fixes this issue:</p>
<blockquote>
<p>Can you redraw the plot without coloring each line by track?</p>
</blockquote>
<p>You can see this in action in <a href="https://chatgpt.com/share/678f1dee-4af0-8000-befe-6df0a8d70fba" target="_blank" rel="noopener">this saved chat</a>
, in the second prompt. Here is the updated code suggested by ChatGPT:</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='c'># Create the visualization without coloring by track</span></span>
<span><span class='nf'><a href='https://ggplot2.tidyverse.org/reference/ggplot.html'>ggplot</a></span><span class='o'>(</span><span class='nv'>billboard_long</span>, <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/aes.html'>aes</a></span><span class='o'>(</span>x <span class='o'>=</span> <span class='nv'>week</span>, y <span class='o'>=</span> <span class='nv'>rank</span>, group <span class='o'>=</span> <span class='nv'>track</span><span class='o'>)</span><span class='o'>)</span> <span class='o'>+</span></span>
<span>  <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/geom_path.html'>geom_line</a></span><span class='o'>(</span>alpha <span class='o'>=</span> <span class='m'>0.3</span>, color <span class='o'>=</span> <span class='s'>"blue"</span><span class='o'>)</span> <span class='o'>+</span></span>
<span>  <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/scale_continuous.html'>scale_y_reverse</a></span><span class='o'>(</span><span class='o'>)</span> <span class='o'>+</span>  <span class='c'># Reverse the y-axis since rank 1 is the top position</span></span>
<span>  <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/labs.html'>labs</a></span><span class='o'>(</span></span>
<span>    title <span class='o'>=</span> <span class='s'>"Song Rank vs. Week Number"</span>,</span>
<span>    x <span class='o'>=</span> <span class='s'>"Week Number"</span>,</span>
<span>    y <span class='o'>=</span> <span class='s'>"Rank"</span>,</span>
<span>    caption <span class='o'>=</span> <span class='s'>"Data: Billboard (tidyr package)"</span></span>
<span>  <span class='o'>)</span> <span class='o'>+</span></span>
<span>  <span class='nf'><a href='https://ggplot2.tidyverse.org/reference/ggtheme.html'>theme_minimal</a></span><span class='o'>(</span><span class='o'>)</span></span>
</code></pre>
<img src="https://posit-open-source.netlify.app/blog/tidyverse/2025/learn-tidyverse-ai/figs/unnamed-chunk-2-1.png" width="700px" style="display: block; margin: auto;" />
</div>
<p>Note, however, that the only change wasn&rsquo;t omitting the <code>color = track</code> aesthetic mapping. The <code>alpha</code> level is also changed (from 0.6 to 0.3) without a justification for that change and the lines are colored <code>&quot;blue&quot;</code>. None of these are <em>bad</em> or <em>wrong</em> choices, but they can be confusing for new learners. Similarly, using <a href="https://ggplot2.tidyverse.org/reference/ggtheme.html" target="_blank" rel="noopener"><code>theme_minimal()</code></a>
 is not a bad or wrong choice either<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>, but it&rsquo;s not <em>necessary</em>, but this might not be obvious to a new learner.</p>
<p>Furthermore, while ChatGPT &ldquo;solves&rdquo; the problem, a thorough code review reveals a number of not-so-great things about the answer that can be confusing for new learners or promote poor coding practices:</p>
<ul>
<li>The code loads packages that are not necessary: tidyr and ggplot2 packages are sufficient for this code, we don&rsquo;t also need dplyr. Additionally, learners coming from R for Data Science likely expect <a href="https://tidyverse.tidyverse.org" target="_blank" rel="noopener"><code>library(tidyverse)</code></a>
 in analysis code, instead of loading the packages individualy.</li>
<li>There is no need to load the <code>billboard</code> dataset, it&rsquo;s available to use once the tidyr package is loaded. Additionally, quotes are not needed, <code>data(billboard)</code> also works.</li>
<li>The code mixes up tidyverse and base R styles:
<ul>
<li>Changing the type of <code>week</code> to numeric can be done in a <a href="https://dplyr.tidyverse.org/reference/mutate.html" target="_blank" rel="noopener"><code>mutate()</code></a>
 statement with the tidyverse, which would then warrant loading the dplyr package.</li>
<li>This can also be done within <a href="https://tidyr.tidyverse.org/reference/pivot_longer.html" target="_blank" rel="noopener"><code>pivot_longer()</code></a>
 with the <code>names_transform</code> argument.</li>
</ul>
</li>
</ul>
<p>All of these are addressable with further prompts, as I&rsquo;ve done at <a href="https://chatgpt.com/share/678f1dee-4af0-8000-befe-6df0a8d70fba" target="_blank" rel="noopener">the saved chat</a>
, in the last two prompts. But doing so requires being able to identify these issues and explicitly asking for corrections. In practice, I wouldn&rsquo;t have asked ChatGPT to correct everything for me, I would have stopped after the first suggestion, which was a pretty good starting point, and made the improvements myself. However, a new learner might assume (and based on my experience seeing lots of new learner code, <em>does</em> assume) the first answer is the <em>right</em> and <em>good</em> or <em>best</em> answer since (1) it looks reasonable and (2) it works, sort of.</p>
<p>Furthermore, requesting improvements in subsequent calls can result in surprising changes that the user hasn&rsquo;t asked for. We saw an example of this above, in updating the alpha level. Similarly, in <a href="https://chatgpt.com/share/678f1dee-4af0-8000-befe-6df0a8d70fba" target="_blank" rel="noopener">the saved chat</a>
 you can see that asking ChatGPT to not load the packages individually but to use <a href="https://tidyverse.tidyverse.org" target="_blank" rel="noopener"><code>library(tidyverse)</code></a>
 instead results in this change as well as not loading the data with a <a href="https://rdrr.io/r/utils/data.html" target="_blank" rel="noopener"><code>data()</code></a>
 call and adding a data transformation step with <a href="https://dplyr.tidyverse.org/reference/mutate.html" target="_blank" rel="noopener"><code>mutate()</code></a>
 to convert <code>week</code> to numeric:</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='c'># Load the tidyverse package</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://tidyverse.tidyverse.org'>tidyverse</a></span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Load the billboard dataset and prepare the data</span></span>
<span><span class='nv'>billboard_long</span> <span class='o'>&lt;-</span> <span class='nv'>billboard</span> <span class='o'>|&gt;</span></span>
<span>  <span class='nf'><a href='https://tidyr.tidyverse.org/reference/pivot_longer.html'>pivot_longer</a></span><span class='o'>(</span></span>
<span>    cols <span class='o'>=</span> <span class='nf'><a href='https://tidyselect.r-lib.org/reference/starts_with.html'>starts_with</a></span><span class='o'>(</span><span class='s'>"wk"</span><span class='o'>)</span>,</span>
<span>    names_to <span class='o'>=</span> <span class='s'>"week"</span>,</span>
<span>    values_to <span class='o'>=</span> <span class='s'>"rank"</span>,</span>
<span>    names_prefix <span class='o'>=</span> <span class='s'>"wk"</span>,</span>
<span>    values_drop_na <span class='o'>=</span> <span class='kc'>TRUE</span></span>
<span>  <span class='o'>)</span> <span class='o'>|&gt;</span></span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='o'>(</span>week <span class='o'>=</span> <span class='nf'><a href='https://rdrr.io/r/base/numeric.html'>as.numeric</a></span><span class='o'>(</span><span class='nv'>week</span><span class='o'>)</span><span class='o'>)</span>  <span class='c'># Convert week to numeric</span></span></code></pre>
</div>
<p>Both of these are welcome changes, but it can be surprising to a new learner why they&rsquo;re combined with updating the <a href="https://rdrr.io/r/base/library.html" target="_blank" rel="noopener"><code>library()</code></a>
 call. This is happening because with each call ChatGPT is &ldquo;trying again&rdquo; &ndash; it&rsquo;s not just editing the previous answer but it&rsquo;s regenerating an answer with additional context.</p>
<p>I should also note that ChatGPT generally gives better responses when asking about sample datasets because the model has probably been exposed to them somewhere in the training data. Next, let&rsquo;s try a non-sample dataset.</p>
<h2 id="case-study-2-data-cleaning">Case study 2: Data cleaning
</h2>
<p>The next example is a lot more vague as it&rsquo;s a task that, if someone asked me for help, I would reply with &ldquo;Can you share the data with me?&rdquo;, but ChatGPT happily generates an answer. That&rsquo;s probably one of the reasons why people love these tools, they never respond to a question with another question, at least not in my experience.</p>
<p>Below is the prompt for this case study. I&rsquo;ll provide it with no background first so you can read it as the AI tool would &ldquo;read&rdquo; it without any background.</p>
<blockquote>
<p>Another variable that needs some cleaning up is <code>membership_status</code>. Currently it should either be <code>NA</code> or contain some text that says &ldquo;Select &hellip; to register for this group&rdquo;. Recode this variable to say <code>&quot;Closed&quot;</code> if the current value is <code>NA</code> or <code>&quot;Open&quot;</code> otherwise. Save the resulting dataset with this new variables as <code>clubs</code>, i.e., overwrite the original data frame. Then, display the first 10 rows of the dataset, moving <code>membership_status</code> to the beginning of the dataset to make sure it appears in the output in your rendered document.</p>
</blockquote>
<p>This time, let&rsquo;s try <a href="https://claude.ai/" target="_blank" rel="noopener">Claude</a>
 by Anthropic. Below is the first response:</p>
<blockquote>
<p>I&rsquo;ll help you clean up the membership_status variable. Let&rsquo;s break this down into steps:</p>
</blockquote>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='c'># Recode membership_status to "Closed" if NA, "Open" otherwise</span></span>
<span><span class='nv'>clubs</span><span class='o'>$</span><span class='nv'>membership_status</span> <span class='o'>&lt;-</span> <span class='nf'><a href='https://rdrr.io/r/base/ifelse.html'>ifelse</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/NA.html'>is.na</a></span><span class='o'>(</span><span class='nv'>clubs</span><span class='o'>$</span><span class='nv'>membership_status</span><span class='o'>)</span>, <span class='s'>"Closed"</span>, <span class='s'>"Open"</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Reorder columns to put membership_status first</span></span>
<span><span class='nv'>clubs</span> <span class='o'>&lt;-</span> <span class='nv'>clubs</span><span class='o'>[</span>, <span class='nf'><a href='https://rdrr.io/r/base/c.html'>c</a></span><span class='o'>(</span><span class='s'>"membership_status"</span>, <span class='nf'><a href='https://generics.r-lib.org/reference/setops.html'>setdiff</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/names.html'>names</a></span><span class='o'>(</span><span class='nv'>clubs</span><span class='o'>)</span>, <span class='s'>"membership_status"</span><span class='o'>)</span><span class='o'>)</span><span class='o'>]</span></span>
<span></span>
<span><span class='c'># Display first 10 rows</span></span>
<span><span class='nf'><a href='https://rdrr.io/r/utils/head.html'>head</a></span><span class='o'>(</span><span class='nv'>clubs</span>, <span class='m'>10</span><span class='o'>)</span></span></code></pre>
</div>
<blockquote>
<p>This code will:</p>
<ul>
<li>Use <a href="https://rdrr.io/r/base/ifelse.html" target="_blank" rel="noopener"><code>ifelse()</code></a>
 to recode the variable based on whether it&rsquo;s NA</li>
<li>Reorder the columns to put membership_status first</li>
<li>Show the first 10 rows of the modified dataset</li>
</ul>
<p>Would you like me to explain any part of this solution in more detail?</p>
</blockquote>
<p>I like the offer to explain more at the end! However, the suggested code does not use the tidyverse. In fact, it&rsquo;s perhaps surprising that it uses R, this could very well have been a task for Python or anoher language commonly used for data science problems.</p>
<p>Let&rsquo;s try again:</p>
<blockquote>
<p>Can you suggest an answer that uses the tidyverse instead of base R?</p>
</blockquote>
<p>And here is the result:</p>
<blockquote>
<p>Here&rsquo;s how to accomplish the same tasks using tidyverse functions:</p>
</blockquote>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='nv'>clubs</span> <span class='o'>&lt;-</span> <span class='nv'>clubs</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='o'>(</span>membership_status <span class='o'>=</span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/if_else.html'>if_else</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/NA.html'>is.na</a></span><span class='o'>(</span><span class='nv'>membership_status</span><span class='o'>)</span>, </span>
<span>                                   <span class='s'>"Closed"</span>, </span>
<span>                                   <span class='s'>"Open"</span><span class='o'>)</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/relocate.html'>relocate</a></span><span class='o'>(</span><span class='nv'>membership_status</span><span class='o'>)</span></span>
<span></span>
<span><span class='nv'>clubs</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> </span>
<span>  <span class='nf'><a href='https://rdrr.io/r/utils/head.html'>head</a></span><span class='o'>(</span><span class='m'>10</span><span class='o'>)</span></span></code></pre>
</div>
<blockquote>
<p>This tidyverse solution:</p>
<ul>
<li>Uses mutate() with <a href="https://dplyr.tidyverse.org/reference/if_else.html" target="_blank" rel="noopener"><code>if_else()</code></a>
 to recode the variable</li>
<li>Uses relocate() to move membership_status to the front</li>
<li>Shows the first 10 rows using head()</li>
</ul>
<p>The tidyverse version is more readable and follows the principle of chaining operations with the pipe operator (<code>%&gt;%</code>). <a href="https://dplyr.tidyverse.org/reference/if_else.html" target="_blank" rel="noopener"><code>if_else()</code></a>
 is the tidyverse equivalent of base R&rsquo;s <a href="https://rdrr.io/r/base/ifelse.html" target="_blank" rel="noopener"><code>ifelse()</code></a>
, with stricter type checking.</p>
<p>Would you like me to explain any of these functions in more detail?</p>
</blockquote>
<p>We&rsquo;re getting there! For new learners of the tidyverse, there are still a few aspects of this code that might be misleading:</p>
<ul>
<li>It doesn&rsquo;t use the base pipe operator (<code>|&gt;</code>), which is the pipe operator used in R for Data Science.</li>
<li>Line breaks and indentation does not follow <a href="https://style.tidyverse.org/pipes.html#long-lines" target="_blank" rel="noopener">tidyverse style guidelines</a>
, which suggest that if the arguments to a function don&rsquo;t all fit on one line, each argument should go on its own line.</li>
<li>If <code>clubs</code> is a tibble, printing it will only display the first 10 rows anyway, so there&rsquo;s no need for the <a href="https://rdrr.io/r/utils/head.html" target="_blank" rel="noopener"><code>head()</code></a>
 call.</li>
</ul>
<p>Once again, it&rsquo;s possible to ask the tool to make these updates. At the time of developing this example, Claude didn&rsquo;t provide a sharing link for the conversation (it does now!), but I&rsquo;ve saved it at <a href="https://gist.github.com/mine-cetinkaya-rundel/c74dc7c5f2a27a846574edd063988431" target="_blank" rel="noopener">https://gist.github.com/mine-cetinkaya-rundel/c74dc7c5f2a27a846574edd063988431</a>
. Even with vague prompts like &ldquo;If clubs is a tibble, it&rsquo;ll only print out the first 10 rows anyway,&rdquo; it does exactly what we would want it to do, resulting in the following:</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='nv'>clubs</span> <span class='o'>&lt;-</span> <span class='nv'>clubs</span> <span class='o'>|&gt;</span></span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='o'>(</span>membership_status <span class='o'>=</span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/if_else.html'>if_else</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/NA.html'>is.na</a></span><span class='o'>(</span><span class='nv'>membership_status</span><span class='o'>)</span>, <span class='s'>"Closed"</span>, <span class='s'>"Open"</span><span class='o'>)</span><span class='o'>)</span> <span class='o'>|&gt;</span></span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/relocate.html'>relocate</a></span><span class='o'>(</span><span class='nv'>membership_status</span><span class='o'>)</span></span>
<span></span>
<span><span class='nv'>clubs</span></span></code></pre>
</div>
<p>The operative word here being &ldquo;want&rdquo;. Once again, someone with enough experience with R and the tidyverse would not explicitly ask for these improvements; they would just make them themselves and carry on. But someone who is just learning the tidyverse would likely stop much earlier. In my experience, many new learners stop after the very first prompt, which looks unfamiliar, and hence potentially intimidating. For learners of the tidyverse, the simple &ldquo;Can you do this with the tidyverse?&rdquo; can be a very useful prompt improvement that gets them majority of the way there.</p>
<h2 id="case-study-3-web-scraping">Case study 3: Web scraping
</h2>
<p>For the third and last example we&rsquo;ll try scraping some data from the web, specifically some <a href="https://www.usclimatedata.com/climate/durham/north-carolina/united-states/usnc0192" target="_blank" rel="noopener">structured North Carolina weather data</a>
. For this example, I&rsquo;ve used <a href="https://www.perplexity.ai/" target="_blank" rel="noopener">perplexity.ai</a>
.</p>
<p>My first prompt was:</p>
<blockquote>
<p>Write code for scraping data from <a href="https://www.usclimatedata.com/climate/durham/north-carolina/united-states/usnc0192" target="_blank" rel="noopener">https://www.usclimatedata.com/climate/durham/north-carolina/united-states/usnc0192</a>
.</p>
</blockquote>
<p>This resulted in an answer using Python, BeautifulSoup, and pandas. So I followed up with:</p>
<blockquote>
<p>Use R instead.</p>
</blockquote>
<p>This resulted in the following.</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='c'># Load required libraries</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://rvest.tidyverse.org/'>rvest</a></span><span class='o'>)</span></span>
<span><span class='c'>#&gt; </span></span>
<span><span class='c'>#&gt; Attaching package: 'rvest'</span></span>
<span></span><span><span class='c'>#&gt; The following object is masked from 'package:readr':</span></span>
<span><span class='c'>#&gt; </span></span>
<span><span class='c'>#&gt;     guess_encoding</span></span>
<span></span><span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://dplyr.tidyverse.org'>dplyr</a></span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Define the URL for Durham, North Carolina climate data</span></span>
<span><span class='nv'>url</span> <span class='o'>&lt;-</span> <span class='s'>"https://www.usclimatedata.com/climate/durham/north-carolina/united-states/usnc0192"</span></span>
<span></span>
<span><span class='c'># Read the HTML content from the website</span></span>
<span><span class='nv'>webpage</span> <span class='o'>&lt;-</span> <span class='nf'><a href='http://xml2.r-lib.org/reference/read_xml.html'>read_html</a></span><span class='o'>(</span><span class='nv'>url</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Extract the table containing climate data</span></span>
<span><span class='nv'>climate_table</span> <span class='o'>&lt;-</span> <span class='nv'>webpage</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>  <span class='nf'><a href='https://rvest.tidyverse.org/reference/rename.html'>html_nodes</a></span><span class='o'>(</span><span class='s'>"table"</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>  <span class='nv'>.</span><span class='o'>[[</span><span class='m'>1</span><span class='o'>]</span><span class='o'>]</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> <span class='c'># Assuming the first table contains the relevant data</span></span>
<span>  <span class='nf'><a href='https://rvest.tidyverse.org/reference/html_table.html'>html_table</a></span><span class='o'>(</span>fill <span class='o'>=</span> <span class='kc'>TRUE</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Convert the table to a data frame</span></span>
<span><span class='nv'>climate_data</span> <span class='o'>&lt;-</span> <span class='nf'><a href='https://rdrr.io/r/base/as.data.frame.html'>as.data.frame</a></span><span class='o'>(</span><span class='nv'>climate_table</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Display the scraped data</span></span>
<span><span class='nf'><a href='https://rdrr.io/r/base/print.html'>print</a></span><span class='o'>(</span><span class='nv'>climate_data</span><span class='o'>)</span></span>
<span><span class='c'>#&gt;                                              JanJa FebFe MarMa AprAp MayMa</span></span>
<span><span class='c'>#&gt; 1             Average high in ºF Av. high Hi 49.00  53.0 62.00 71.00 79.00</span></span>
<span><span class='c'>#&gt; 2               Average low in ºF Av. low Lo 28.00  29.0 37.00 46.00 56.00</span></span>
<span><span class='c'>#&gt; 3 Av. precipitation in inch Av. precip. Pre.  4.45   3.7  4.69  3.43  4.61</span></span>
<span><span class='c'>#&gt;   JunJu</span></span>
<span><span class='c'>#&gt; 1 85.00</span></span>
<span><span class='c'>#&gt; 2 65.00</span></span>
<span><span class='c'>#&gt; 3  4.02</span></span>
<span></span></code></pre>
</div>
<p>Additionally, the suggestion included optional code for writing the data to CSV even though it wasn&rsquo;t part of the prompt, though also not bad practice either when scraping data from the web.</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='c'># Optional: Save the data to a CSV file</span></span>
<span><span class='nf'><a href='https://rdrr.io/r/utils/write.table.html'>write.csv</a></span><span class='o'>(</span><span class='nv'>climate_data</span>, <span class='s'>"durham_climate_data.csv"</span>, row.names <span class='o'>=</span> <span class='kc'>FALSE</span><span class='o'>)</span></span></code></pre>
</div>
<p>First, this code doesn&rsquo;t give us what we want:</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='nv'>climate_data</span></span>
<span><span class='c'>#&gt;                                              JanJa FebFe MarMa AprAp MayMa</span></span>
<span><span class='c'>#&gt; 1             Average high in ºF Av. high Hi 49.00  53.0 62.00 71.00 79.00</span></span>
<span><span class='c'>#&gt; 2               Average low in ºF Av. low Lo 28.00  29.0 37.00 46.00 56.00</span></span>
<span><span class='c'>#&gt; 3 Av. precipitation in inch Av. precip. Pre.  4.45   3.7  4.69  3.43  4.61</span></span>
<span><span class='c'>#&gt;   JunJu</span></span>
<span><span class='c'>#&gt; 1 85.00</span></span>
<span><span class='c'>#&gt; 2 65.00</span></span>
<span><span class='c'>#&gt; 3  4.02</span></span>
<span></span></code></pre>
</div>
<p>We only have the first six months (the first table) and the formatting is not great, especially for the column names. Additionally, this doesn&rsquo;t look like a tidy data frame &ndash; a better organization would be months in rows and temperatures in columns.</p>
<div class="highlight">
</div>
<p>Let&rsquo;s follow up with a better articulated prompt:</p>
<blockquote>
<p>Update the code to scrape data for all months from both of the tables on the website and organizing the data with months as rows and temperature types as columns.</p>
</blockquote>
<p>Here is the updated suggestion:</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://rvest.tidyverse.org/'>rvest</a></span><span class='o'>)</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://dplyr.tidyverse.org'>dplyr</a></span><span class='o'>)</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://tidyr.tidyverse.org'>tidyr</a></span><span class='o'>)</span></span>
<span></span>
<span><span class='nv'>url</span> <span class='o'>&lt;-</span> <span class='s'>"https://www.usclimatedata.com/climate/durham/north-carolina/united-states/usnc0192"</span></span>
<span></span>
<span><span class='c'># Read HTML content</span></span>
<span><span class='nv'>webpage</span> <span class='o'>&lt;-</span> <span class='nf'><a href='http://xml2.r-lib.org/reference/read_xml.html'>read_html</a></span><span class='o'>(</span><span class='nv'>url</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Extract all tables</span></span>
<span><span class='nv'>climate_tables</span> <span class='o'>&lt;-</span> <span class='nv'>webpage</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>  <span class='nf'><a href='https://rvest.tidyverse.org/reference/rename.html'>html_nodes</a></span><span class='o'>(</span><span class='s'>"table"</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>  <span class='nf'><a href='https://rvest.tidyverse.org/reference/html_table.html'>html_table</a></span><span class='o'>(</span>header <span class='o'>=</span> <span class='kc'>TRUE</span>, fill <span class='o'>=</span> <span class='kc'>TRUE</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Check if we have at least 2 tables</span></span>
<span><span class='kr'>if</span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/length.html'>length</a></span><span class='o'>(</span><span class='nv'>climate_tables</span><span class='o'>)</span> <span class='o'>&gt;=</span> <span class='m'>2</span><span class='o'>)</span> <span class='o'>&#123;</span></span>
<span>  <span class='c'># Process first table (Average High Temperatures)</span></span>
<span>  <span class='nv'>high_temp</span> <span class='o'>&lt;-</span> <span class='nv'>climate_tables</span><span class='o'>[[</span><span class='m'>1</span><span class='o'>]</span><span class='o'>]</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>    <span class='nf'><a href='https://dplyr.tidyverse.org/reference/select.html'>select</a></span><span class='o'>(</span>Month <span class='o'>=</span> <span class='m'>1</span>, High <span class='o'>=</span> <span class='m'>2</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>    <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='o'>(</span>High <span class='o'>=</span> <span class='nf'><a href='https://rdrr.io/r/base/numeric.html'>as.numeric</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/grep.html'>gsub</a></span><span class='o'>(</span><span class='s'>"[^0-9.]"</span>, <span class='s'>""</span>, <span class='nv'>High</span><span class='o'>)</span><span class='o'>)</span><span class='o'>)</span></span>
<span>  </span>
<span>  <span class='c'># Process second table (Average Low Temperatures)</span></span>
<span>  <span class='nv'>low_temp</span> <span class='o'>&lt;-</span> <span class='nv'>climate_tables</span><span class='o'>[[</span><span class='m'>2</span><span class='o'>]</span><span class='o'>]</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>    <span class='nf'><a href='https://dplyr.tidyverse.org/reference/select.html'>select</a></span><span class='o'>(</span>Month <span class='o'>=</span> <span class='m'>1</span>, Low <span class='o'>=</span> <span class='m'>2</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> </span>
<span>    <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='o'>(</span>Low <span class='o'>=</span> <span class='nf'><a href='https://rdrr.io/r/base/numeric.html'>as.numeric</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/grep.html'>gsub</a></span><span class='o'>(</span><span class='s'>"[^0-9.]"</span>, <span class='s'>""</span>, <span class='nv'>Low</span><span class='o'>)</span><span class='o'>)</span><span class='o'>)</span></span>
<span>  </span>
<span>  <span class='c'># Combine and organize data</span></span>
<span>  <span class='nv'>combined_data</span> <span class='o'>&lt;-</span> <span class='nv'>high_temp</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>    <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate-joins.html'>full_join</a></span><span class='o'>(</span><span class='nv'>low_temp</span>, by <span class='o'>=</span> <span class='s'>"Month"</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span></span>
<span>    <span class='nf'><a href='https://dplyr.tidyverse.org/reference/arrange.html'>arrange</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/factor.html'>factor</a></span><span class='o'>(</span><span class='nv'>Month</span>, levels <span class='o'>=</span> <span class='nv'>month.name</span><span class='o'>)</span><span class='o'>)</span></span>
<span>  </span>
<span>  <span class='c'># Display cleaned data</span></span>
<span>  <span class='nf'><a href='https://rdrr.io/r/base/print.html'>print</a></span><span class='o'>(</span><span class='nv'>combined_data</span><span class='o'>)</span></span>
<span>  </span>
<span>  <span class='c'># Save to CSV</span></span>
<span>  <span class='nf'><a href='https://rdrr.io/r/utils/write.table.html'>write.csv</a></span><span class='o'>(</span><span class='nv'>combined_data</span>, <span class='s'>"durham_temperatures.csv"</span>, row.names <span class='o'>=</span> <span class='kc'>FALSE</span><span class='o'>)</span></span>
<span><span class='o'>&#125;</span> <span class='kr'>else</span> <span class='o'>&#123;</span></span>
<span>  <span class='kr'><a href='https://rdrr.io/r/base/stop.html'>stop</a></span><span class='o'>(</span><span class='s'>"Required tables not found - website structure may have changed"</span><span class='o'>)</span></span>
<span><span class='o'>&#125;</span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'># A tibble: 3 × 3</span></span></span>
<span><span class='c'>#&gt;   Month                                       High   Low</span></span>
<span><span class='c'>#&gt;   <span style='color: #555555; font-style: italic;'>&lt;chr&gt;</span>                                      <span style='color: #555555; font-style: italic;'>&lt;dbl&gt;</span> <span style='color: #555555; font-style: italic;'>&lt;dbl&gt;</span></span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>1</span> Average high in ºF Av. high Hi             49    89   </span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>2</span> Average low in ºF Av. low Lo               28    70   </span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>3</span> Av. precipitation in inch Av. precip. Pre.  4.45  3.94</span></span>
<span></span></code></pre>
</div>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='c'>#&gt; [1] TRUE</span></span>
<span></span></code></pre>
</div>
<p>There is a lot going on here, especially for a new learner, and the result is ultimately not what we want:</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='nv'>combined_data</span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'># A tibble: 3 × 3</span></span></span>
<span><span class='c'>#&gt;   Month                                       High   Low</span></span>
<span><span class='c'>#&gt;   <span style='color: #555555; font-style: italic;'>&lt;chr&gt;</span>                                      <span style='color: #555555; font-style: italic;'>&lt;dbl&gt;</span> <span style='color: #555555; font-style: italic;'>&lt;dbl&gt;</span></span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>1</span> Average high in ºF Av. high Hi             49    89   </span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>2</span> Average low in ºF Av. low Lo               28    70   </span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>3</span> Av. precipitation in inch Av. precip. Pre.  4.45  3.94</span></span>
<span></span></code></pre>
</div>
<div class="highlight">
</div>
<p>Let&rsquo;s try one more time, following up with this prompt:</p>
<blockquote>
<p>This is not what I wanted. First scrape the data from the two tables for months January to June and July to December. Then put them together. Then reshape the data to have months as rows and temperature types as columns.</p>
</blockquote>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://rvest.tidyverse.org/'>rvest</a></span><span class='o'>)</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://dplyr.tidyverse.org'>dplyr</a></span><span class='o'>)</span></span>
<span><span class='kr'><a href='https://rdrr.io/r/base/library.html'>library</a></span><span class='o'>(</span><span class='nv'><a href='https://tidyr.tidyverse.org'>tidyr</a></span><span class='o'>)</span></span>
<span></span>
<span><span class='nv'>url</span> <span class='o'>&lt;-</span> <span class='s'>"https://www.usclimatedata.com/climate/durham/north-carolina/united-states/usnc0192"</span></span>
<span><span class='nv'>webpage</span> <span class='o'>&lt;-</span> <span class='nf'><a href='http://xml2.r-lib.org/reference/read_xml.html'>read_html</a></span><span class='o'>(</span><span class='nv'>url</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Extract all climate tables (4 tables total)</span></span>
<span><span class='nv'>all_tables</span> <span class='o'>&lt;-</span> <span class='nv'>webpage</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> </span>
<span>  <span class='nf'><a href='https://rvest.tidyverse.org/reference/rename.html'>html_nodes</a></span><span class='o'>(</span><span class='s'>"table.climate-table"</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> </span>
<span>  <span class='nf'><a href='https://rvest.tidyverse.org/reference/html_table.html'>html_table</a></span><span class='o'>(</span>header <span class='o'>=</span> <span class='kc'>TRUE</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Process temperature data from first two tables (Jan-Jun and Jul-Dec)</span></span>
<span><span class='nv'>high_temp</span> <span class='o'>&lt;-</span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/bind_rows.html'>bind_rows</a></span><span class='o'>(</span></span>
<span>  <span class='nv'>all_tables</span><span class='o'>[[</span><span class='m'>1</span><span class='o'>]</span><span class='o'>]</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/select.html'>select</a></span><span class='o'>(</span>Month <span class='o'>=</span> <span class='m'>1</span>, High <span class='o'>=</span> <span class='m'>2</span><span class='o'>)</span>,</span>
<span>  <span class='nv'>all_tables</span><span class='o'>[[</span><span class='m'>2</span><span class='o'>]</span><span class='o'>]</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/select.html'>select</a></span><span class='o'>(</span>Month <span class='o'>=</span> <span class='m'>1</span>, High <span class='o'>=</span> <span class='m'>2</span><span class='o'>)</span></span>
<span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='o'>(</span>High <span class='o'>=</span> <span class='nf'><a href='https://rdrr.io/r/base/numeric.html'>as.numeric</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/grep.html'>gsub</a></span><span class='o'>(</span><span class='s'>"°F"</span>, <span class='s'>""</span>, <span class='nv'>High</span><span class='o'>)</span><span class='o'>)</span><span class='o'>)</span></span>
<span><span class='c'>#&gt; Error in all_tables[[1]]: subscript out of bounds</span></span>
<span></span><span></span>
<span><span class='nv'>low_temp</span> <span class='o'>&lt;-</span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/bind_rows.html'>bind_rows</a></span><span class='o'>(</span></span>
<span>  <span class='nv'>all_tables</span><span class='o'>[[</span><span class='m'>3</span><span class='o'>]</span><span class='o'>]</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/select.html'>select</a></span><span class='o'>(</span>Month <span class='o'>=</span> <span class='m'>1</span>, Low <span class='o'>=</span> <span class='m'>2</span><span class='o'>)</span>,</span>
<span>  <span class='nv'>all_tables</span><span class='o'>[[</span><span class='m'>4</span><span class='o'>]</span><span class='o'>]</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/select.html'>select</a></span><span class='o'>(</span>Month <span class='o'>=</span> <span class='m'>1</span>, Low <span class='o'>=</span> <span class='m'>2</span><span class='o'>)</span></span>
<span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='o'>(</span>Low <span class='o'>=</span> <span class='nf'><a href='https://rdrr.io/r/base/numeric.html'>as.numeric</a></span><span class='o'>(</span><span class='nf'><a href='https://rdrr.io/r/base/grep.html'>gsub</a></span><span class='o'>(</span><span class='s'>"°F"</span>, <span class='s'>""</span>, <span class='nv'>Low</span><span class='o'>)</span><span class='o'>)</span><span class='o'>)</span></span>
<span><span class='c'>#&gt; Error in all_tables[[3]]: subscript out of bounds</span></span>
<span></span><span></span>
<span><span class='c'># Combine and format final dataset</span></span>
<span><span class='nv'>climate_data</span> <span class='o'>&lt;-</span> <span class='nv'>high_temp</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> </span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate-joins.html'>left_join</a></span><span class='o'>(</span><span class='nv'>low_temp</span>, by <span class='o'>=</span> <span class='s'>"Month"</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> </span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='o'>(</span>Month <span class='o'>=</span> <span class='nf'><a href='https://rdrr.io/r/base/factor.html'>factor</a></span><span class='o'>(</span><span class='nv'>Month</span>, levels <span class='o'>=</span> <span class='nv'>month.name</span><span class='o'>)</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> </span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/arrange.html'>arrange</a></span><span class='o'>(</span><span class='nv'>Month</span><span class='o'>)</span> <span class='o'><a href='https://magrittr.tidyverse.org/reference/pipe.html'>%&gt;%</a></span> </span>
<span>  <span class='nf'><a href='https://dplyr.tidyverse.org/reference/select.html'>select</a></span><span class='o'>(</span><span class='nv'>Month</span>, <span class='nv'>High</span>, <span class='nv'>Low</span><span class='o'>)</span></span>
<span></span>
<span><span class='c'># Display formatted results</span></span>
<span><span class='nf'><a href='https://rdrr.io/r/base/print.html'>print</a></span><span class='o'>(</span><span class='nv'>climate_data</span><span class='o'>)</span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'># A tibble: 3 × 3</span></span></span>
<span><span class='c'>#&gt;   Month  High   Low</span></span>
<span><span class='c'>#&gt;   <span style='color: #555555; font-style: italic;'>&lt;fct&gt;</span> <span style='color: #555555; font-style: italic;'>&lt;dbl&gt;</span> <span style='color: #555555; font-style: italic;'>&lt;dbl&gt;</span></span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>1</span> <span style='color: #BB0000;'>NA</span>    49    89   </span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>2</span> <span style='color: #BB0000;'>NA</span>    28    70   </span></span>
<span><span class='c'>#&gt; <span style='color: #555555;'>3</span> <span style='color: #BB0000;'>NA</span>     4.45  3.94</span></span>
<span></span></code></pre>
</div>
<p>Unfortunately this gives an error. However, the presentation in the answer from Perplexity makes it seem like the data were scraped successfully since a table with rows as months and columns as temperature types is included in the explanation:</p>
<pre><code>       Month High Low
1    January   50  30
2   February   54  32
3      March   63  39
4      April   72  47
5        May   79  56
6       June   85  64
7       July   89  69
8     August   87  68
9  September   81  60
10   October   72  49
11  November   63  39
12  December   54  32
</code></pre>
<p>I&rsquo;m not sure how these data were extracted, but we know it&rsquo;s not with the R code provided above. The values are also not correct (e.g., high and low in January should be 49 and 28, instead), so it&rsquo;s completely unclear where they&rsquo;re coming from. You can follow along with this thread at <a href="https://www.perplexity.ai/search/write-code-for-scraping-data-f-6kRnwLDTTpe8vItl08Bo3g" target="_blank" rel="noopener">https://www.perplexity.ai/search/write-code-for-scraping-data-f-6kRnwLDTTpe8vItl08Bo3g</a>
. I tried a few more prompts and finally gave up. While the other two tasks were much more straightforward, the web scraping task seems to be more difficult for this tool. I should note that I used different services for each task, and the lack of success in this last one might be due to that as well.</p>
<p>Ultimately, though, as the complexity of the task increases, it (understandably) gets more difficult to get to straightforward and new-learner-friendly answers with simple prompts.</p>
<h2 id="tips-and-good-practices">Tips and good practices
</h2>
<p>I&rsquo;ll wrap up this post with some tips and good practices for using AI tools for (tidyverse) code generation. But first, a disclaimer &ndash; this landscape is changing super quickly. Today&rsquo;s good practices might not be the best approaches for tomorrow. However, the following have held true over the last year so there&rsquo;s a good chance they will remain relevant for some time into the future.</p>
<ol>
<li>
<p><strong>Provide context and engineer prompts:</strong> This might be obvious, but it should be stated. Providing context, even something as simple as &ldquo;use R&rdquo; or &ldquo;use tidyverse&rdquo; can go a long way in getting a semi-successful first suggestion. Then, continue engineering the prompt until you achieve the results you need, being more articulate about what you want at each step. This is easier said than done, though, for new learners. If you don&rsquo;t know what the right answer should look like, it&rsquo;s much harder to be articulate in your prompt to get to that answer. On the other hand, if you do know what the right answer should look like, you might be more likely to just write the code yourself, instead of coaching the AI tool to get there. Another potentially helpful tip is to end your initial prompt with something like &ldquo;Ask me any clarifying questions before you begin&rdquo;. This way you don&rsquo;t have to think about all the necessary context at once, you can get the tool to ask you for some of the details.</p>
</li>
<li>
<p><strong>Check for errors:</strong> This also seems obvious &ndash; you should run the code the tool suggests and check for errors. If the code gives an error, this is easy to catch and potentially easy to address. However, sometimes the code suggests arguments that don&rsquo;t exist that R might silently ignore. These might be unneeded arguments or a needed argument but not used properly due to how it&rsquo;s called or the value it&rsquo;s set to. Such errors are more difficult to identify, particularly in functions you might not be familiar with.</p>
</li>
<li>
<p><strong>Run the code it gives you, line-by-line, even if the code is in a pipeline:</strong> Tidyverse data transformation pipelines and ggplot layers are easy to run at once, with the code doing many things with one execution prompt, compared to Base R code where you execute each line of code separately. The scaffolded nature of these pipelines are very nice for keeping all steps associated with a task together and not generating unnecessary interim objects along the way. However, it requires self-discipline to inspect the code line-by-line as opposed to just inspecting the final output. For example, I regularly encounter unnecessary <a href="https://dplyr.tidyverse.org/reference/group_by.html" target="_blank" rel="noopener"><code>group_by()</code></a>
/<a href="https://dplyr.tidyverse.org/reference/group_by.html" target="_blank" rel="noopener"><code>ungroup()</code></a>
s or <a href="https://dplyr.tidyverse.org/reference/select.html" target="_blank" rel="noopener"><code>select()</code></a>
s steps injected into pipelines. Identifying these requires running the pipeline code line-by-line, and then you can remove or modify them to simplify your answer. My recommendation would be to approach the working with AI tools for code generation with an &ldquo;I&rsquo;m trying to learn how to do this&rdquo; attitude. It&rsquo;s then natural to investigate and interact with each step of the answer. If you approach it with a &ldquo;Solve this for me&rdquo; attitude, it&rsquo;s a lot harder to be critical of seemingly functioning and seemingly good enough code.</p>
</li>
<li>
<p><strong>Improve code smell:</strong> While I don&rsquo;t have empirical evidence for this, I believe for humans, taste for good code develops faster than ability. For LLMs, this is the opposite. These tools will happily barf out code that runs without regard to cohesive syntax, avoiding redundancies, etc. Therefore, it&rsquo;s essential to &ldquo;clean up&rdquo; the suggested code to improve its &ldquo;code smell&rdquo;. Below are some steps I regularly use:</p>
<ul>
<li>Remove redundant library calls.</li>
<li>Use <code>pkg::function()</code> syntax only as needed and consistently.</li>
<li>Avoid mixing and matching base R and tidyverse syntax (e.g., in one step finding mean in a <a href="https://dplyr.tidyverse.org/reference/summarise.html" target="_blank" rel="noopener"><code>summarize()</code></a>
 call and in another step as mean of a vector, <code>mean(df$var)</code>.</li>
<li>Remove unnecessary <a href="https://rdrr.io/r/base/print.html" target="_blank" rel="noopener"><code>print()</code></a>
 statements.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></li>
<li>Consider whether code comments address the &ldquo;why&rdquo; or the &ldquo;what.&rdquo; If comments describe relatively self-documenting code, consider removing them.</li>
</ul>
</li>
<li>
<p><strong>Stuck? Start a new chat:</strong> Each new prompt in a chat/thread is evaluated within the context of previous prompts in that thread. If you&rsquo;re stuck and not getting to a good answer after modifying your prompt a few times, start fresh with a new chat/thread instead.</p>
</li>
<li>
<p><strong>Use code completion tools sparingly if you&rsquo;re a new user:</strong> Code completion tools, like <a href="https://github.com/features/copilot" target="_blank" rel="noopener">GitHub Copilot</a>
, can be huge productivity boosters. But, especially for new learners, they can also be huge distractions as they tend to take action before the user is able to complete a thought in their head. My recommendation for new learners would be to avoid these tools altogether until they get a little faster at going from idea to code by themselves, or at a minimum until they feel like they can consistently write high quality prompts that generate the desired code on the first try. And my recommendation for anyone using code completion tools is to experiment with wait time between prompt and code generation and set a time that works for well for themselves. In my experience, the default wait time can be too short, resulting in code being generated before I can finish writing my prompt or reviewing the prompt I write.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p>
</li>
<li>
<p><strong>Use AI tools for help with getting help:</strong> So far the focus of this post has been on generating code to accomplish certain data science tasks. Perhaps the most important, and most difficult, data science task is asking good questions when you&rsquo;re stuck troubleshooting. And it usually requires or is greatly helped by creating a minimum reproducible example and using tools like <a href="https://reprex.tidyverse.org/" target="_blank" rel="noopener">reprex</a>
. This often starts with creating a small dataset with certain features, and AI tools can be pretty useful for generating such toy examples.</p>
</li>
</ol>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>And maybe a future post on teaching R in the age of AI!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>In fact, it&rsquo;s my preferred ggplot2 theme!&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>I&rsquo;ve never seen as many <a href="https://rdrr.io/r/base/print.html" target="_blank" rel="noopener"><code>print()</code></a>
 statements in R code as I have over the last year of reading code from hundreds of students who use AI tools to generate code for their assignments with varying levels of success! I don&rsquo;t know why these tools love <a href="https://rdrr.io/r/base/print.html" target="_blank" rel="noopener"><code>print()</code></a>
 statements!&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>For example, in RStudio, go to Tools &gt; Global Options &gt; select Copilot from the left menu and adjust &ldquo;Show code suggestions after keyboard idle (ms)&rdquo;.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2025/learn-tidyverse-ai/thumbnail-wd.jpg" length="855755" type="image/jpeg" />
    </item>
    <item>
      <title>Tip - use Positron to choose colors for your project brand</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2025-01-15-quarto-tip-brand-positron/</link>
      <pubDate>Wed, 15 Jan 2025 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2025-01-15-quarto-tip-brand-positron/</guid>
      <dc:creator>Carlos Scheidegger</dc:creator><description><![CDATA[<p>In today&rsquo;s Quarto Tip, we show you how <a href="https://positron.posit.co" target="_blank" rel="noopener">Positron</a>

enables a very easy workflow for creating and changing colors in your <code>_brand.yml</code>
file. Quarto 1.6 includes <a href="https://posit-dev.github.io/brand-yml/" target="_blank" rel="noopener">support for <code>_brand.yml</code></a>
, a
standard for creating a single style configuration file that is usable across formats and
systems.</p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/Mly_DK-2BnI"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




<p>Additional links:</p>
<ul>
<li><a href="https://quarto.org/docs/blog/posts/2024-11-25-1.6-release/index.html" target="_blank" rel="noopener">Quarto 1.6 release post</a>
</li>
<li><a href="https://positron.posit.co/download.html" target="_blank" rel="noopener">Download Positron</a>
</li>
<li><a href="https://quarto.org/docs/authoring/brand.html" target="_blank" rel="noopener">Quarto&rsquo;s <code>_brand.yml</code> documentation</a>
</li>
</ul>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2025-01-15-quarto-tip-brand-positron/brand.png" length="165176" type="image/png" />
    </item>
    <item>
      <title>Joining the ggplot2 team</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2025/joining-ggplot2/</link>
      <pubDate>Thu, 09 Jan 2025 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2025/joining-ggplot2/</guid>
      <dc:creator>Teun Van den Brand</dc:creator><description><![CDATA[<!--
TODO:
* [x] Look over / edit the post's title in the yaml
* [x] Edit (or delete) the description; note this appears in the Twitter card
* [x] Pick category and tags (see existing with [`hugodown::tidy_show_meta()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html))
* [x] Find photo & update yaml metadata
* [x] Create `thumbnail-sq.jpg`; height and width should be equal
* [x] Create `thumbnail-wd.jpg`; width should be >5x height
* [x] [`hugodown::use_tidy_thumbnails()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html)
* [ ] Add intro sentence, e.g. the standard tagline for the package
* [ ] [`usethis::use_tidy_thanks()`](https://usethis.r-lib.org/reference/use_tidy_thanks.html)
-->
<p>Hello there! I&rsquo;ve been working on ggplot2 for a while now, and I&rsquo;d like to tell you how that came about and what it is like.</p>
<h2 id="how-i-got-involved">How I got involved
</h2>
<p>My journey into learning R started in 2017 during an internship at the EMBL-EBI. The main gripe about base R plotting that drove me into ggplot2&rsquo;s arms were the arcane invocations to get anything else than one of the pre-approved chart types. In contrast, ggplot2 absorbs a bunch of small paper cuts, is very compositional in nature while remaining highly customisable. In a bid to &ldquo;learn from the mistakes of others&rdquo; rather than (continue to copiously) make my own, I became active on Stack Overflow answering questions and solving plotting issues. For posterity: this was in the days before you could ask an large language model for personalised advice and actual humans were equally frustrated on both sides of the question.</p>
<p>I was keeping track of solutions to common problems in a personal cookbook that had its own arcane invocations. To give a bit of flavour: much of the cookbook was about preparing gtables (the data structure that comes out of building a plot) for combining and aligning plots. <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> The cookbook eventually grew into my first ggplot2 extension package: <a href="https://teunbrand.github.io/ggh4x/" target="_blank" rel="noopener">ggh4x</a>
. Perhaps that package would be best subtitled: &lsquo;Remedies to my common ggplot2 ailments&rsquo;. It contains a bunch of miscellaneous functions ranging from reorganising facets to putting minor ticks on the axes. The nature of the package was also its downside, as ggh4x lacked any sense of scope (and still does, as befits any first package).</p>
<p>Around the time when I was really getting into ggplot extensions, <a href="https://github.com/EvaMaeRey" target="_blank" rel="noopener">Gina Reynolds</a>
 had started organising a meeting for people who build ggplot2 extensions. It is an interesting place to meet others and hear about their packages and how they face interacting with the ggplot2 extension system. I started attending with some degree of regularity and made a discussion place on GitHub. We now use this for general exchange of ideas, but also package specific issues.</p>
<p>Meanwhile, the questions on Stack Overflow kept directing my attention at the ggplot2 issue tracker every once in a while. After lurking in there for a bit, I started my first informal contributions to ggplot2 itself by answering the simple stuff just as I did on Stack Overflow. It may not seem like much of a contribution, but in retrospect, answering issues helps triaging them: it separates those issues that need additional changes in ggplot2 from those that do not. My first &lsquo;proper contribution&rsquo; in the shape of a pull request was in 2020. It replaced 3 lines of code with 2 lines of code to benefit type stability (this was prior to <a href="https://vctrs.r-lib.org/" target="_blank" rel="noopener">vctrs</a>
)<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<p>In 2022, I commented &ldquo;I&rsquo;d be willing to take a stab at this&rdquo; on an issue proposing a large refactor of the guide system. I like to think it was this precise moment that Thomas, the project lead after having taken over for Hadley, took notice and later invited me to join the team<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>. This new guide system ended up laying the foundation for <a href="https://teunbrand.github.io/legendry/" target="_blank" rel="noopener">legendry</a>
, so it wasn&rsquo;t entirely out of unselfish reasons that I volunteered. At any rate, this is a great opportunity to fill big shoes on a major R project, so I&rsquo;m very excited to have joined!</p>
<h2 id="becoming-an-insider">Becoming an insider
</h2>
<p>Part of being on the team is straightforward. You triage issues. You fix bugs. You implement new features. At the point that I joined, I had already done these things as an outsider. The only thing that really changes is that you get the keys to the kingdom: you can now close issues and merge pull requests <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>. You&rsquo;re then trusted to wield this power wisely. You then hope you do.</p>
<p>At the time I joined the most active maintainers were Thomas, Claus and Hiroaki. I was surprised to learn that really most communication happens on GitHub and it is all public discussion. Even more abstract coordination that does not neatly fit into a single issue, like preparing a new release, didn&rsquo;t occur behind closed doors. I think what made my introduction to the team more awkward than it needed to be was that GitHub issues is not really a good place for announcements where you can say &lsquo;Hi everyone, this person is on the team now and will be doing stuff in the project&rsquo;. I had interacted with the other active maintainers before, so I wasn&rsquo;t a completely alien actor, but I felt some unclarity lingered longer than it ought have. Perhaps I should more assertively have introduced myself <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>.</p>
<p>However, by the time posit::conf(2024) was over, I&rsquo;ve met 6 out of the 9 other authors in person. I have more thoughts about conf and my first time in the United States, but it has been amazing to meet all these people in person whose work you&rsquo;ve been admiring for a while!</p>
<h2 id="maintaining-ggplot2">Maintaining ggplot2
</h2>
<p>The ggplot2 package has both the blessing and the curse of being a popular package. One the one hand, it is a blessing that people care about the project, post issues that they find and make intermittent contributions. The curse is that it is such a staple in the R ecosystem, that almost any change will inadvertently affect somebody else&rsquo;s code. Not only because ggplot2 is widely used, but also because people have been &hellip;creative&hellip; with how they are using ggplot2. The art of making changes is to largely affect plots in a good way.</p>
<p>The first big project I was rummaging through was the guide system I proposed to rewrite. The guide system had never been advertised as an official extension point, but naturally that didn&rsquo;t preclude people from using it as an extension point anyway.<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup> So in addition to rewriting the system, we also had to prevent terribly breaking extensions that relied on the old system. In some cases, this meant sending out PRs to other packages to be compatible with both systems.</p>
<p>Having worked through a good number of issues at this point in time, I can see some emergent patterns. Different patterns can be partially explained by different audiences. The regular user wants to be empowered to execute their vision of a plot effectively. Maintainers of extensions would often like things to work consistently or change a very obscure line somewhere that they have identified as blocking a niche use case. Teachers would like their students to get stuck less often, which often involves improving error messages. All in all, there is no shortage of issues to work through.</p>
<p>The next big thing we&rsquo;re working on is some practical necromancy in getting themeable aesthetics resurrected, which was <a href="https://www.danaseidel.com/2018-09-01-ATidySummer/" target="_blank" rel="noopener">initiated by Dana Paige Seidel</a>
 all the way back in 2018! We&rsquo;d like the theme to be a home for more default choices than just non-data elements. Default layer aesthetics are a start, but we plan on putting in default palettes too.</p>
<h2 id="a-few-words-of-thanks">A few words of thanks
</h2>
<p>I&rsquo;ve been plucked from a level of relative obscurity &mdash;a package maintainer that has this weird miscellaneous package&mdash; into the path of a flagship R project, for which I&rsquo;m very grateful. First and foremost I&rsquo;m thankful to Thomas Lin Pedersen, who has put me into this position and steers the ggplot2 project. Secondly to Hadley Wickham and the rest of the tidyverse team, who make me feel included; both at conf and during regular meetings<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup>. Thirdly, the co-authors I met during conf: Claus Wilke, for whose workshop I TA&rsquo;d, but also Kara Woo and Winston Chang. Lastly, I&rsquo;d like to thank Posit the company for contracting me to do work I also enjoy as a hobby!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Luckily, we don&rsquo;t have to think about this <em>at all</em>, thanks to the <a href="https://patchwork.data-imaginist.com/" target="_blank" rel="noopener">patchwork</a>
 package!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>I&rsquo;m omitting here that I also had to write 50 lines of tests for this small change&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>How much this actually reflects any truth is for any of us to guess and for Thomas to know. Later, I learned that this was also <a href="https://www.data-imaginist.com/posts/2016-10-31-becoming-the-intern/" target="_blank" rel="noopener">how Thomas himself was roped into the project</a>
!&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>After review though. You&rsquo;re not given <em>that</em> much power!&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>But I&rsquo;m not celebrated for my social graces :)&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>I don&rsquo;t have a moral high ground here: I was one of the worst offenders!&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p>Mostly for The Golden Hex Sticker though!&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2025/joining-ggplot2/thumbnail-wd.jpg" length="412209" type="image/jpeg" />
    </item>
    <item>
      <title>tidymodels Internship for 2025</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2025/tidymodels-2025-internship/</link>
      <pubDate>Wed, 08 Jan 2025 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2025/tidymodels-2025-internship/</guid>
      <dc:creator>Max Kuhn</dc:creator><description><![CDATA[<p>We are chuffed once again to offer a summer internship with the tidymodels team.</p>
<p>We&rsquo;ve had eight previous summer interns and these led to the creation of a number of new packages: <a href="https://agua.tidymodels.org/" target="_blank" rel="noopener">agua</a>
, <a href="https://applicable.tidymodels.org/" target="_blank" rel="noopener">applicable</a>
, <a href="https://rstudio.github.io/bundle/" target="_blank" rel="noopener">bundle</a>
, <a href="https://butcher.tidymodels.org/" target="_blank" rel="noopener">butcher</a>
, <a href="https://shinymodels.tidymodels.org/" target="_blank" rel="noopener">shinymodels</a>
, <a href="https://spatialsample.tidymodels.org/" target="_blank" rel="noopener">spatialsample</a>
, and <a href="https://stacks.tidymodels.org/" target="_blank" rel="noopener">stacks</a>
. Our own <a href="https://www.simonpcouch.com/" target="_blank" rel="noopener">Simon Couch</a>
 is a former intern who won <a href="https://community.amstat.org/jointscsg-section/awards/john-m-chambers" target="_blank" rel="noopener">an award</a>
 for his work.</p>
<p>This year, the primary focus is on expanding our feature selection capabilities. Some of this will involve new recipe steps and other functions. Towards the end of the internship, there might be time to work on other things, too!</p>
<p>To apply, make sure that you have a GitHub handle and follow this link:</p>
<p><strong><a href="https://posit.co/job-detail/?gh_jid=6323043003" target="_blank" rel="noopener"><code>https://posit.co/job-detail/?gh_jid=6323043003</code></a>
</strong></p>
<p>The internship is US-based.</p>
<p>If you want to know what the internship is like, a few of our alumni have written about it:</p>
<ul>
<li><a href="https://www.alexpghayes.com/post/2018-08-10_a-summer-with-rstudio/" target="_blank" rel="noopener"><em>A summer with RStudio</em> (2018)</a>
</li>
<li><a href="https://fbchow.rbind.io/2018/07/27/rstudio-summer-internship/" target="_blank" rel="noopener"><em>RStudio Summer Internship</em> (2018)</a>
</li>
<li><a href="https://education.rstudio.com/blog/2019/12/this-is-not-like-the-others/" target="_blank" rel="noopener"><em>This Is Not Like the Others</em> (2019)</a>
</li>
<li><a href="https://education.rstudio.com/blog/2020/06/tidymodels-internship/" target="_blank" rel="noopener"><em>Tidymodels Internship</em> (2020)</a>
</li>
<li><a href="https://www.mm218.dev/posts/2022-08-15-last-summer/" target="_blank" rel="noopener"><em>I know what I did last summer</em> (2022)</a>
</li>
</ul>
<p>We can&rsquo;t wait to get started and look forward to reading your applications.</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2025/tidymodels-2025-internship/thumbnail-wd.jpg" length="159114" type="image/jpeg" />
    </item>
    <item>
      <title>Use `meta` &#43; `include` to customize reusable content</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2024-12-12-includes-meta/</link>
      <pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2024-12-12-includes-meta/</guid>
      <dc:creator>Ashley Henry</dc:creator><description><![CDATA[<div class="callout callout-tip" role="note" aria-label="Tip">
<div class="callout-header">
<span class="callout-title">Re-posted from posit.co</span>
</div>
<div class="callout-body">
<p>This post was originally published on the <a href="https://posit.co/blog/quarto-meta-shortcode-variables/" target="_blank" rel="noopener">Posit Blog</a>
.</p>
<p>The worked example below is also available at: <a href="https://github.com/quarto-dev/quarto-examples/tree/main/websites/quarto-meta-includes" target="_blank" rel="noopener">Source</a>
 | <a href="https://examples.quarto.pub/quarto-meta-includes/" target="_blank" rel="noopener">Live Website</a>
</p>
</div>
</div>
<p>There may be times when you would like to single-source content across multiple pages/files to reduce the risk of errors, produce consistent content that is easy to maintain, and ultimately save valuable time. <a href="https://quarto.org/" target="_blank" rel="noopener">Quarto</a>
 (an open-source technical publishing system), provides an <a href="https://quarto.org/docs/authoring/includes.html" target="_blank" rel="noopener">Includes</a>
 feature (the equivalent of an R Markdown &ldquo;child&rdquo; document) that allows you to reuse content across multiple documents/files/pages.</p>
<p>To achieve this, simply create chunks of content (text, tables, code, callouts, images, etc.) and then insert it using the Include shortcode: <code>{{&lt; include _content.qmd &gt;}}</code>.</p>
<p>Typically, you must keep your content general enough so it can be reused in several places. In other words, if you needed to add a name or an image that is specific to that file, you would assume that you wouldn&rsquo;t be able to use an include, or you would have to use several smaller includes sewn into uniquely written content.</p>
<p>But what if you need your single-sourced content to be more specific? You can use Includes with <code>meta</code> shortcode (variables) to add precise values defined at the file level.</p>
<h2 id="walkthrough-example">Walkthrough example
</h2>
<p>Let us walk you through an example of how to achieve this.</p>
<p>Before you begin:</p>
<ul>
<li>Quarto version 1.5+ was used for this walkthrough example.</li>
<li>This has been tested with both new and existing Website projects.</li>
<li>A <code>var</code> shortcode enables you to insert content from the project or file level.</li>
<li>The <code>meta</code> shortcode allows you to insert content from Pandoc metadata (e.g., YAML at the top of the document and/or in <code>_quarto.yml</code>).</li>
<li>As you preview your site, pages will be rendered and updated. However, if you make changes to global options (e.g. <code>_quarto.yml</code> or included files) you need to fully re-render your site to have all of the changes reflected. Consequently, you should always fully <code>quarto render</code> your site before deploying it, even if you have already previewed changes to some pages with the preview server.</li>
</ul>
<h3 id="create-the-content">Create the content:
</h3>
<p>Here is an example of a file with content we want to reuse across several pages.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">In this document, we cover facts that are unique to the state, like the state&#39;s population, its flower, and animal.
</span></span></code></pre></td></tr></table>
</div>
</div><p>This content is general enough to use as each state&rsquo;s introduction but lacks the facts that are unique to each state. So, we could insert the Include into each state&rsquo;s file and then add specific content that is unique to the state:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">---
</span></span><span class="line"><span class="cl">title: New York
</span></span><span class="line"><span class="cl">---
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{&lt; include _snippets/state-intro.qmd &gt;}}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">New York has a geographical size of 54,555, making it the 27th largest state with an estimated population size of 19.8 million.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">The state&#39;s flower is the Rose, as shown below:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">![](images/ny/flower.png)
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="why-are-we-doing-this">Why are we doing this?
</h3>
<p>Instead of copying and pasting this content into each file, and then updating it with each state&rsquo;s fact (which introduces a higher risk of making an error), we can use meta variables to insert specific values.</p>
<h3 id="lets-execute">Let&rsquo;s execute
</h3>
<p>First, I create a file within my <code>_snippets</code> directory named <code>facts.qmd</code>. Throughout the file, I am going to insert a unique <code>meta</code> variable for each occurrence that I want the content to be specific to the state:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">{{&lt; meta state &gt;}} covers approximately {{&lt; meta square-miles &gt;}} making it the {{&lt; meta size-rank &gt;}} largest state in the United States. As of 2023, {{&lt; meta state &gt;}} has an approximate population of about {{&lt; meta population &gt;}}.
</span></span></code></pre></td></tr></table>
</div>
</div><p>I can define each of the <code>meta</code> variables within the individual file that I plan on reusing this content. So, in my <code>ny.qmd</code> file, I define each variable in the YAML metadata. Then, insert the <code>facts.qmd</code> file with the undefined meta shortcodes using an include:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">---
</span></span><span class="line"><span class="cl">title: New York
</span></span><span class="line"><span class="cl">state-abbr: ny
</span></span><span class="line"><span class="cl">state: New York
</span></span><span class="line"><span class="cl">size-rank: 27th
</span></span><span class="line"><span class="cl">square-miles: 54,555
</span></span><span class="line"><span class="cl">population: 19.8 million
</span></span><span class="line"><span class="cl">---
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{&lt; include _snippets/facts.qmd &gt;}}
</span></span></code></pre></td></tr></table>
</div>
</div><p>As you can see, the rendered file has the meta shortcodes populated with the definitions that you assigned to each value in the file&rsquo;s YAML.</p>
<img src="https://posit-open-source.netlify.app/blog/quarto/2024-12-12-includes-meta/images/img1.png" style="box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3); border-radius: 5px;" data-fig-align="center" />
<p>But, I would also like to add the state&rsquo;s flower and animal with images of each. You can achieve this by editing the document to add this information and images:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">{{&lt; include _snippets/facts.qmd &gt;}}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">New York&#39;s official flower is the Rose:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">![](../images/ny/flower.png)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">And the official animal is the Beaver:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">![](../images/ny/animal.png)
</span></span></code></pre></td></tr></table>
</div>
</div><p>Or, you can get creative and use <code>meta</code> shortcodes in your image paths so you can continue to manage all of the content in a single file:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">{{&lt; meta state &gt;}}&#39;s official flower is the {{&lt; meta flower &gt;}}, pictured below:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">![<span class="nt">The official {{&lt; meta state &gt;}} state flower, the {{&lt; meta flower &gt;}}</span>](<span class="na">../images/{{&lt; meta state-abbr &gt;}}/flower.png</span>)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Lastly, {{&lt; meta state &gt;}}&#39;s official animal is the {{&lt; meta animal &gt;}}, pictured below:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">![<span class="nt">The official {{&lt; meta state &gt;}} state animal, the {{&lt; meta animal &gt;}}</span>](<span class="na">../images/{{&lt; meta state-abbr &gt;}}/animal.png</span>)
</span></span></code></pre></td></tr></table>
</div>
</div><p>As you can see, my image paths have <code>{{&lt; meta state-abbr &gt;}}</code> which is defined in the new-york file as &ldquo;ny&rdquo;.</p>
<p>When we render the project, the image path updates to /images/ny/flower.png pointing to the existing flower image in the <code>ny</code> directory:</p>
<img src="https://posit-open-source.netlify.app/blog/quarto/2024-12-12-includes-meta/images/img2.png" style="box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3); border-radius: 5px;" data-fig-align="center" />
<p>In theory, you could do this for each state as long as each directory follows the same naming conventions, i.e., <code>pa/flower.png</code> and <code>vt/flower.png</code>.</p>
<p>This does require an organized and scalable approach since the images will have to follow the same directory and file-naming conventions, but in doing so, you can create individualized pages and images using a single include.</p>
<h3 id="the-rendered-example">The rendered example
</h3>
<p>Here is New York&rsquo;s page:</p>
<img src="https://posit-open-source.netlify.app/blog/quarto/2024-12-12-includes-meta/images/img3.png" style="box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3); border-radius: 5px;" data-fig-align="center" />
<p>Here is Pennsylvania&rsquo;s page:</p>
<img src="https://posit-open-source.netlify.app/blog/quarto/2024-12-12-includes-meta/images/img4.png" style="box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3); border-radius: 5px;" data-fig-align="center" />
<p>Each page was built using a single (shared) file:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">{{&lt; include _snippets/facts.qmd &gt;}}
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="learn-more-about-quarto-includes">Learn more about Quarto Includes
</h2>
<p>Quarto&rsquo;s Includes feature allows you to improve your content creation process by reducing redundancy and maintaining consistency across multiple documents. Whether you&rsquo;re managing technical documentation, educational materials, or any other content, this approach can help you save time, reduce errors, and deliver polished results.</p>
<p>Learn more with these resources:</p>
<ul>
<li><a href="https://quarto.org/docs/get-started/" target="_blank" rel="noopener">Get Started - Quarto</a>
</li>
<li><a href="https://quarto.org/docs/authoring/includes.html" target="_blank" rel="noopener">Quarto - Includes</a>
</li>
<li><a href="https://quarto.org/docs/authoring/variables.html#meta" target="_blank" rel="noopener">Quarto - meta Variables</a>
</li>
<li>An overview of <a href="https://technicalwriterhq.com/writing/technical-writing/single-source-authoring/" class="external">Single Source Authoring</a></li>
</ul>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2024-12-12-includes-meta/thumbnail.jpg" length="60237" type="image/jpeg" />
    </item>
    <item>
      <title>Quarto website video series</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2024-12-04-websites-workshop/</link>
      <pubDate>Wed, 04 Dec 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2024-12-04-websites-workshop/</guid>
      <dc:creator>Charlotte Wickham</dc:creator>
      <dc:creator>Mine Çetinkaya-Rundel</dc:creator><description><![CDATA[<p>Do you need a professional website to showcase your work? If you&rsquo;ve used Quarto to produce a document, you&rsquo;ve already got the technical skills to create a Quarto website. In this video series, taught by <a href="https://www.cwick.co.nz/" target="_blank" rel="noopener">Charlotte Wickham</a>
 and <a href="https://emilhvitfeldt.com/" target="_blank" rel="noopener">Emil Hvitfeldt</a>
, you&rsquo;ll learn everything else you need to build a website and customize its appearance.</p>
<p><a href="https://www.youtube.com/playlist?list=PLitrm9Undxcu7eExaTg9Y-JYLv9O6uxGu" target="_blank" rel="noopener">YouTube Playlist</a>
</p>
<h2 id="quarto-websites-1-build-your-homepage">Quarto Websites 1: Build your homepage
</h2>
<p>In this video, you&rsquo;ll get a running start by using a template we&rsquo;ve designed to be functional and attractive, and that will serve as a foundation for the rest of the video series. You&rsquo;ll customize the content of your homepage, and how it looks, and along the way learn about the two key files in a Quarto website index.qmd and _quarto.yml. Finally, you&rsquo;ll learn one way to publish your website so other people can see it.</p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/l7r24gTEkEY"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




<p>Links: <a href="https://quarto.org/docs/websites/website-about.html" target="_blank" rel="noopener">About pages</a>
 | <a href="https://quarto.org/docs/output-formats/html-themes.html#basic-options" target="_blank" rel="noopener">YAML appearance options</a>
</p>
<p>Code: <a href="https://github.com/EmilHvitfeldt/website-template" target="_blank" rel="noopener">Starter</a>
 | <a href="https://github.com/cwickham/quarto-website-video/tree/v0.1" target="_blank" rel="noopener">Final</a>
</p>
<h2 id="quarto-websites-2-add-pages-and-navigation">Quarto Websites 2: Add pages and navigation
</h2>
<p>Now you&rsquo;ve got a homepage, you&rsquo;ll likely want to add some other pages. In this video, learn how to add pages to your website, and help people find them, by adding them to your website navigation.</p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/k65E-8PXZmA"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




<p>Links: <a href="https://icons.getbootstrap.com/" target="_blank" rel="noopener">Bootstrap icons</a>
 | <a href="https://quarto.org/docs/websites/website-navigation.html#top-navigation" target="_blank" rel="noopener">Navigation bar options</a>
 | <a href="https://quarto.org/docs/websites/website-navigation.html" target="_blank" rel="noopener">Quarto website navigation</a>
</p>
<p>Code: <a href="Starter%20source%20code:%20https://github.com/cwickham/quarto-website-video/tree/v0.1">Starter</a>
 | <a href="https://github.com/cwickham/quarto-website-video/tree/v0.2" target="_blank" rel="noopener">Final</a>
</p>
<h2 id="quarto-websites-3-customize-appearance-with-cssscss">Quarto Websites 3: Customize appearance with CSS/SCSS
</h2>
<p>You now have a set of content you are happy with on your website, but how do you customize the look and feel of your site beyond options set in YAML? In this video, you&rsquo;ll start by learning the basics of CSS and SCSS and how to make good design choices. Then, you&rsquo;ll see how to apply these choices to your Quarto website.</p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/pAN2Hiq0XGs"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




<p>Links: <a href="https://colourcontrast.cc/" target="_blank" rel="noopener">Color contrast checker</a>
 | <a href="https://fonts.google.com/" target="_blank" rel="noopener">Google fonts</a>
</p>
<p>Code: <a href="https://github.com/cwickham/quarto-website-video/tree/v0.2" target="_blank" rel="noopener">Starter</a>
 | <a href="https://github.com/cwickham/quarto-website-video/tree/v0.3" target="_blank" rel="noopener">Final</a>
</p>
<h2 id="quarto-websites-4-add-lists-of-content-with-listings">Quarto Websites 4: Add lists of content with listings
</h2>
<p>Adding a listing page to your website is a great way to showcase your projects, talks, publications or blog posts. In this video you&rsquo;ll learn how to create a listing page in Quarto and see two ways to populate it with content: Quarto documents, or a yaml file.</p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/bv_Cw-3HI1Y"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




<p>Links: <a href="https://quarto.org/docs/websites/website-listings.html" target="_blank" rel="noopener">Listings</a>
 | <a href="https://www.andrewheiss.com/teaching/" target="_blank" rel="noopener">Andrew Heiss&rsquo; teaching listing</a>
</p>
<p>Code: <a href="https://github.com/cwickham/quarto-website-video/tree/v0.3" target="_blank" rel="noopener">Starter</a>
 | <a href="https://github.com/cwickham/quarto-website-video/tree/v0.4" target="_blank" rel="noopener">Final</a>
</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2024-12-04-websites-workshop/quarto-websites.jpg" length="55926" type="image/jpeg" />
    </item>
    <item>
      <title>Quarto dashboards video series</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2024-11-22-dashboards-workshop/</link>
      <pubDate>Fri, 22 Nov 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2024-11-22-dashboards-workshop/</guid>
      <dc:creator>Charlotte Wickham</dc:creator>
      <dc:creator>Mine Çetinkaya-Rundel</dc:creator><description><![CDATA[<p>If you&rsquo;ve been looking to get your head around Quarto dashboards,
check out the Quarto dashboards video series by <a href="https://mine-cr.com/" target="_blank" rel="noopener">Mine Çetinkaya-Rundel</a>
.</p>
<p>Materials: <a href="https://youtube.com/playlist?list=PLitrm9UndxcsapDsLimKGn3dEjQZy5vYs&amp;si=oLK2D1PuyF9MKVon" target="_blank" rel="noopener">YouTube playlist</a>
 | <a href="https://mine.quarto.pub/quarto-dashboards/" target="_blank" rel="noopener">Slides</a>
 | <a href="https://github.com/mine-cetinkaya-rundel/olympicdash" target="_blank" rel="noopener">Starter code</a>
</p>
<h2 id="1-hello-quarto-dashboards">1. Hello, Quarto Dashboards
</h2>
<p>Start by getting to know Quarto dashboards and make your very first dashboard using either R or Python and share it online. <a href="https://mine.quarto.pub/quarto-dashboards/1-hello-dashboards/#/title-slide" target="_blank" rel="noopener">Slides</a>
</p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/HW7QbqI4fH0"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




<h2 id="2-quarto-dashboards-components">2. Quarto Dashboards Components
</h2>
<p>Then, build up your arsenal of dashboard components to add navigation, sidebars, tabsets, value boxes, and fine-tune layout. <a href="https://mine.quarto.pub/quarto-dashboards/2-dashboard-components/#/title-slide" target="_blank" rel="noopener">Slides</a>
</p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/KdsQgwaY950"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




<h2 id="3-quarto-dashboards-theming-and-styling">3. Quarto Dashboards Theming and Styling
</h2>
<p>Finally, make your dashboard pop by adding a theme and making styling tweaks. <a href="https://mine.quarto.pub/quarto-dashboards/3-theming-styling/#/title-slide" target="_blank" rel="noopener">Slides</a>
</p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/NigWSB-jG4Y"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2024-11-22-dashboards-workshop/quarto-dashboards.jpg" length="80578" type="image/jpeg" />
    </item>
    <item>
      <title>posit::conf(2024) Quarto talks</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2024-11-06-conf-talks/</link>
      <pubDate>Wed, 06 Nov 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2024-11-06-conf-talks/</guid>
      <dc:creator>Mine Çetinkaya-Rundel and Charlotte Wickham</dc:creator><description><![CDATA[<p>Videos of posit::conf(2024) talks are now posted <a href="https://www.youtube.com/watch?v=s_Vh9HIeLVg&amp;list=PL9HYL-VRX0oSFkdF4fJeY63eGDvgofcbn" target="_blank" rel="noopener">on YouTube</a>
. We have also made playlist of talks that are about using, building with, and building on Quarto.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?si=Xwt6NHL_f4k9agzh&amp;list=PLNUVZZ6hfXX1Y4Is-SbbMF_HutRDJBwiO" 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>
<p>Talks included in this playlist are as follows:</p>
<ul>
<li><a href="https://youtu.be/s_Vh9HIeLVg?si=jsIWeETKQG154dFi" target="_blank" rel="noopener">Updates from Posit, with Hadley Wickham, Charlotte Wickham, George Stagg, and James Blair</a>
</li>
<li><a href="https://youtu.be/KqLxy66B3lQ?si=fe1zVCBozVmWKufO" target="_blank" rel="noopener">Andrew Bray - Closeread: bringing Scrollytelling to Quarto</a>
</li>
<li><a href="https://youtu.be/VJEBg1Ke0lE?si=LUMa5-IF3gWORr3I" target="_blank" rel="noopener">Meghan Hall - Designing and Deploying Internal Quarto Templates</a>
</li>
<li><a href="https://youtu.be/bp1SMhLoz_M?si=tyvyO-FP0AEBV6W2" target="_blank" rel="noopener">David Keyes - Report Design in R: Small Tweaks that Make a Big Difference</a>
</li>
<li><a href="https://youtu.be/fsfoqpQYN2k?si=sDUOZTEBXvXLNVHq" target="_blank" rel="noopener">Mine Çetinkaya-Rundel - Reproducible, dynamic, and elegant books with Quarto</a>
</li>
<li><a href="https://youtu.be/4zy9R26B8kk?si=rO_5BIjTC3ENVC2c" target="_blank" rel="noopener">Cynthia Huang - Quarto for Knowledge Management</a>
</li>
<li><a href="https://youtu.be/UOMcGBMvVdo?si=yo3dFtWScKn06iXy" target="_blank" rel="noopener">Regina Lionheart - Making Waves with R, Python, and Quarto</a>
</li>
<li><a href="https://youtu.be/PITfti4JRiU?si=TMi-CJOi04zViU_p" target="_blank" rel="noopener">Joshua Cook - Quarto: A Multifaceted Publishing Powerhouse for Medical Researchers</a>
</li>
<li><a href="https://youtu.be/U8_Dc_ru8fg?si=-fEK5Ou57f-QhSba" target="_blank" rel="noopener">Tyler Morgan-Wall - Quarto, AI, and the Art of Getting Your Life Back</a>
</li>
<li><a href="https://youtu.be/fzykFa6c3LI?si=wV83nh1WvctfRAiu" target="_blank" rel="noopener">Sean Nguyen - Beyond Dashboards: Dynamic Data Storytelling with Python, R, and Quarto Emails</a>
</li>
<li><a href="https://youtu.be/CySpBKJD5vY?si=zQ2TowaD_Wk0Du8X" target="_blank" rel="noopener">Richie Moluno - JSquarto: Bridging JavaScript Documentation with Quarto&rsquo;s Power</a>
</li>
<li><a href="https://youtu.be/1gUl-vWqScc?si=nLEJ8JsLzBv8UqqT" target="_blank" rel="noopener">Mika Braginsky - DataPages for interactive data sharing using Quarto</a>
</li>
<li><a href="https://youtu.be/ceW3nQssV88?si=caHnzvBHorxWFn00" target="_blank" rel="noopener">Brennan Antone - Democratizing Organizational Surveys with Quarto and Shiny</a>
</li>
</ul>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2024-11-06-conf-talks/images/thumbnail.jpg" length="176419" type="image/jpeg" />
    </item>
    <item>
      <title>posit::conf(2024) Quarto workshop materials</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2024-10-15-conf-workshops-materials/</link>
      <pubDate>Tue, 15 Oct 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2024-10-15-conf-workshops-materials/</guid>
      <dc:creator>Mine Çetinkaya-Rundel and Charlotte Wickham</dc:creator><description><![CDATA[<p>This year at posit::conf(2024) we had three day-long Quarto workshops. The materials from those workshops are available for all to learn from. Additionally, you&rsquo;re welcomed to use them in full or part when talking or teaching about Quarto; they are all released with a <a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener">CC BY-SA 4.0</a>
 license.</p>
<table>
<colgroup>
<col style="width: 70%" />
<col style="width: 30%" />
</colgroup>
<tbody>
<tr>
<td style="text-align: left;"><div width="70.0%" data-layout-align="left">
<p><a href="https://posit-conf-2024.github.io/quarto-intro/" data-heading="Introduction to Quarto"><strong>Introduction to Quarto</strong></a></p>
<p><a href="https://posit-conf-2024.github.io/quarto-intro" class="uri">https://posit-conf-2024.github.io/quarto-intro</a></p>
<p><br />
</p>
<ul>
<li><p>Led by <a href="https://bids.berkeley.edu/people/andrew-bray">Andrew Bray</a>, UC Berkeley</p></li>
<li><p>Ideal for beginners looking to create rich documents</p></li>
</ul>
</div></td>
<td style="text-align: center;"><div width="30.0%" data-layout-align="center">
<p><a href="https://posit-conf-2024.github.io/quarto-intro/"><img src="https://posit-open-source.netlify.app/blog/quarto/2024-10-15-conf-workshops-materials/images/intro.png" data-fig-alt="Illustration of a seaplane." /></a></p>
</div></td>
</tr>
</tbody>
</table>
<table>
<colgroup>
<col style="width: 70%" />
<col style="width: 30%" />
</colgroup>
<tbody>
<tr>
<td style="text-align: left;"><div width="70.0%" data-layout-align="left">
<p><a href="https://posit-conf-2024.github.io/quarto-dashboards/"><strong>Build-a-Dashboard Workshop (with Quarto, R, and/or Python)</strong></a></p>
<p><a href="https://posit-conf-2024.github.io/quarto-dashboards/">https://posit-conf-2024.github.io/quarto-dashboards</a></p>
<p><br />
</p>
<ul>
<li><p>Led by <a href="https://mine-cr.com/">Mine Çetinkaya-Rundel</a>, Posit, PBC, Duke University</p></li>
<li><p>Perfect for those familiar with computational notebooks in R and/or Python who want to create eye-catching dashboards</p></li>
</ul>
</div></td>
<td style="text-align: center;"><div width="30.0%" data-layout-align="center">
<p><a href="https://posit-conf-2024.github.io/quarto-dashboards/"><img src="https://posit-open-source.netlify.app/blog/quarto/2024-10-15-conf-workshops-materials/images/dashboards.png" data-fig-alt="An illustration of a dashboard made with Quarto" /></a></p>
</div></td>
</tr>
</tbody>
</table>
<table>
<colgroup>
<col style="width: 70%" />
<col style="width: 30%" />
</colgroup>
<tbody>
<tr>
<td style="text-align: left;"><div width="70.0%" data-layout-align="left">
<p><a href="https://posit-conf-2024.github.io/quarto-websites/" data-heading="Quarto Websites"><strong>Quarto Websites</strong></a></p>
<p><a href="https://posit-conf-2024.github.io/quarto-websites/">https://posit-conf-2024.github.io/quarto-websites</a></p>
<p><br />
</p>
<ul>
<li><p>Led by <a href="https://www.cwick.co.nz/">Charlotte Wickham</a> and <a href="https://emilhvitfeldt.com/">Emil Hvitfeldt</a>, Posit, PBC</p></li>
<li><p>Great choice for those wanting to build a website from scratch with Quarto</p></li>
</ul>
</div></td>
<td style="text-align: center;"><div width="30.0%" data-layout-align="center">
<p><a href="https://posit-conf-2024.github.io/quarto-websites/"><img src="https://posit-open-source.netlify.app/blog/quarto/2024-10-15-conf-workshops-materials/images/websites.png" data-fig-alt="A diagram showing switching between navbar and sidebar navigation for a Quarto website." /></a></p>
</div></td>
</tr>
</tbody>
</table>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2024-10-15-conf-workshops-materials/images/thumbnail.png" length="747217" type="image/png" />
    </item>
    <item>
      <title>Quarto workshops at posit::conf(2024)</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2024-05-28-conf-workshops/</link>
      <pubDate>Tue, 28 May 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2024-05-28-conf-workshops/</guid>
      <dc:creator>Isabella Velásquez and Mine Çetinkaya-Rundel</dc:creator><description><![CDATA[<p>Join us for posit::conf(2024) in Seattle! On August 12, we&rsquo;re hosting a day of workshops featuring three dedicated to Quarto. Check out the options below and find the workshop that&rsquo;s just right for you. Already found your ideal Quarto workshop? <a href="https://posit.co/conference/" target="_blank" rel="noopener">Register today</a>
!</p>
<p><a href="#introduction-to-quarto"><strong>Introduction to Quarto</strong></a>
</p>
<ul>
<li>
<p>Led by <a href="https://bids.berkeley.edu/people/andrew-bray" target="_blank" rel="noopener">Andrew Bray</a>
, Berkeley University</p>
</li>
<li>
<p>Ideal for beginners looking to create rich documents</p>
</li>
</ul>
<p><a href="#build-a-dashboard-workshop-with-quarto-r-andor-python"><strong>Build-a-Dashboard Workshop (with Quarto, R, and/or Python)</strong></a>
</p>
<ul>
<li>
<p>Led by <a href="https://mine-cr.com/" target="_blank" rel="noopener">Mine Çetinkaya-Rundel</a>
, Posit, PBC, Duke University</p>
</li>
<li>
<p>Perfect for those familiar with computational notebooks in R and/or Python who want to create eye-catching dashboards</p>
</li>
</ul>
<p><a href="#quarto-websites"><strong>Quarto Websites</strong></a>
</p>
<ul>
<li>
<p>Led by <a href="https://www.cwick.co.nz/" target="_blank" rel="noopener">Charlotte Wickham</a>
 and <a href="https://emilhvitfeldt.com/" target="_blank" rel="noopener">Emil Hvitfeldt</a>
, Posit, PBC</p>
</li>
<li>
<p>Great choice for those wanting to build a website from scratch with Quarto</p>
</li>
</ul>
<h2 id="introduction-to-quarto"><strong>Introduction to Quarto</strong>
</h2>
<p>This workshop will prepare you to author a rich array of documents in Quarto, the next generation of R Markdown. Quarto is an open-source scientific and technical publishing system that offers multilingual programming language support to create dynamic and static documents, books, presentations, blogs, and other online resources.</p>
<p>This workshop focuses on single documents. You will learn to create static documents, add interactivity to them with Shiny and HTML widgets, or steer them toward sophisticated scientific documents.</p>
<p>In the afternoon, you&rsquo;ll use the same authoring approaches to create slide presentations in various formats, such as reveal.js, Beamer, and PPTX.</p>
<p><strong>This workshop is for you if you:</strong></p>
<ul>
<li>
<p>Have a basic knowledge of how to use the RStudio IDE,</p>
</li>
<li>
<p>Have some familiarity with Markdown, or</p>
</li>
<li>
<p>Are excited to author flexible single documents like technical reports and slide presentations.</p>
</li>
</ul>
<h2 id="build-a-dashboard-workshop-with-quarto-r-andor-python"><strong>Build-a-Dashboard Workshop (with Quarto, R, and/or Python)</strong>
</h2>
<p>You already analyze and summarize your data in computational notebooks with R and/or Python. What&rsquo;s next? </p>
<p>You can share your insights or allow others to make their own conclusions in eye-catching dashboards and straight-forward to author, design, and deploy Quarto Dashboards, regardless of the language of your data processing, visualization, analysis, etc. With Quarto Dashboards, you can create elegant and production-ready dashboards using a variety of components, including static graphics (ggplot2, Matplotlib, Seaborn, etc.), interactive widgets (Plotly, Leaflet, Jupyter Widgets, htmlwidgets, etc.), tabular data, value boxes, text annotations, and more. Additionally, with intelligent resizing of components, your Quarto Dashboards look great on devices of all sizes.</p>
<p>And importantly, you can author Quarto Dashboards without leaving the comfort of your &ldquo;home&rdquo; &ndash; in plain text markdown with any text editor (VS Code, RStudio, Neovim, etc.) or any notebook editor (JupyterLab, etc.). This workshop will walk you through building an increasingly complex dashboard using various layout options and deploying them as static web pages (with no special server required), as well as with a Shiny Server on the backend for enhanced interactivity.</p>
<p><strong>This workshop is for you if you:</strong></p>
<ul>
<li>
<p>Do data analysis in computational notebooks,</p>
</li>
<li>
<p>Share your results with your audience in static or interactive dashboards and</p>
</li>
<li>
<p>Want to improve the design, user interface, and experience of your dashboards.</p>
</li>
</ul>
<h2 id="quarto-websites"><strong>Quarto Websites</strong>
</h2>
<p>Do you need a professional website to showcase your work? Or have you got an idea for a website at work, but it needs to reflect your organization&rsquo;s brand? If you&rsquo;ve used Quarto to produce a document, you&rsquo;ve already got the technical skills to create a Quarto website. In this workshop, you&rsquo;ll learn everything else you need to build a website and customize its appearance.</p>
<p>You&rsquo;ll get a running start by using a template we&rsquo;ve designed to be functional and attractive but also act as a guide for your learning. Then you&rsquo;ll:</p>
<ul>
<li>
<p>Add pages and navigation, and learn best practices for structuring your content.</p>
</li>
<li>
<p>Master the basics of SCSS and CSS and how they apply to Quarto websites to customize your site&rsquo;s visual appearance.</p>
</li>
<li>
<p>Use listings, a special kind of page, to showcase related content like blog posts, projects, or talks.</p>
</li>
</ul>
<p>By the end of the workshop, you&rsquo;ll have built and published (if you want) a personal website, but the same tools and techniques will apply to any kind of website you might like to build.</p>
<p>We&rsquo;ll assume you&rsquo;ve used Quarto to produce documents, but we won&rsquo;t assume you have any HTML, CSS/SCSS, or Git/GitHub experience, nor will we assume any particular programming language (R, Python, etc.) or level of programming experience.</p>
<p><strong>This workshop is for you if you:</strong></p>
<ul>
<li>
<p>Have used Quarto to generate documents (e.g., HTML, PDF, MS Word, etc.)</p>
</li>
<li>
<p>Are comfortable editing plain text documents (e.g., `.qmd`) in your IDE (e.g., RStudio, Visual Studio Code, etc.) and</p>
</li>
<li>
<p>Want to walk away with your own personal website.</p>
</li>
</ul>
<h2 id="learn-more-about-positconf2024"><strong>Learn more about posit::conf(2024)</strong>
</h2>
<p>Want to explore the complete catalog of posit::conf(2024) workshops and talks?</p>
<ul>
<li>
<p>Workshops on August 12: Head over to our <a href="https://reg.conf.posit.co/flow/posit/positconf24/publiccatalog/page/publiccatalog?search=&amp;search.sessiontype=1675316728702001wr6r" target="_blank" rel="noopener">workshop listing</a>
 to discover detailed information about the courses and instructors.</p>
</li>
<li>
<p>Talks on August 13 and August 14: Peruse the <a href="https://reg.conf.posit.co/flow/posit/positconf24/publiccatalog/page/publiccatalog?search=&amp;tab.day=20240813" target="_blank" rel="noopener">conference agenda</a>
.</p>
<ul>
<li>Tip: For a quick view of all Quarto talks, filter for &ldquo;Quarto&rdquo; under topics.</li>
</ul>
</li>
</ul>
<p>Ready to secure your spot? Visit the <a href="https://posit.co/conference/" target="_blank" rel="noopener">conference website</a>
 for comprehensive details on pricing and the agenda, and <a href="https://reg.conf.posit.co/flow/posit/positconf24/reg/login" target="_blank" rel="noopener">register today</a>
!</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2024-05-28-conf-workshops/images/conf-workshops-thumbnail.png" length="286065" type="image/png" />
    </item>
    <item>
      <title>Tidyverse developer day 2024</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2024/tdd-2024/</link>
      <pubDate>Tue, 09 Apr 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2024/tdd-2024/</guid>
      <dc:creator>Hadley Wickham</dc:creator><description><![CDATA[<!--
TODO:
* [x] Look over / edit the post's title in the yaml
* [x] Edit (or delete) the description; note this appears in the Twitter card
* [x] Pick category and tags (see existing with [`hugodown::tidy_show_meta()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html))
* [x] Find photo & update yaml metadata
* [x] Create `thumbnail-sq.jpg`; height and width should be equal
* [x] Create `thumbnail-wd.jpg`; width should be >5x height
* [x] [`hugodown::use_tidy_thumbnails()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html)
-->
<p>It&rsquo;s been a hot minute since the last one, but we are very excited to announce that the next tidyverse developer day will be after <a href="https://posit.co/conference/" target="_blank" rel="noopener">posit::conf</a>
 in Seattle on August 15, 2024. A big thanks goes to <a href="https://www.fredhutch.org/en.html" target="_blank" rel="noopener">Fred Hutch Cancer Center</a>
 for donating the space!</p>
<p><strong>What is the tidyverse developer day?</strong> TDD is a day of learning and coding to nurture regular contributors to the tidyverse. We&rsquo;ll provide food; you&rsquo;ll bring your laptop and enthusiasm. The tidyverse team and other community helpers will be on hand to help you hit the ground running and/or get over any stumbling blocks that you encounter. Don&rsquo;t have any ideas for something to work on? No problem! We&rsquo;ll be tagging issues in advance to make sure there&rsquo;s lots to do for any- and everyone, regardless of level of expertise.</p>
<p><strong>Who should attend?</strong> Anyone who would like to get better at contributing to the tidyverse! Everyone is welcome regardless of whether you&rsquo;ve never done a PR before, or if you&rsquo;ve already made your 10th package. But you do need a ticket; to provide a fulfilling experience for all attendees we need to carefully manage the ratio of attendees to helpers.</p>
<p><strong>How much does it cost?</strong> $10. This doesn&rsquo;t cover the costs of the event because we don&rsquo;t want to make attendance contingent on your ability to pay, but we&rsquo;ve found some monetary commitment discourages people from taking tickets that they don&rsquo;t end up using. But if the cost would prevent you from attending, please email <a href="mailto:jenny@posit.co">jenny@posit.co</a>
 and we can figure something out.</p>
<p><a href="https://www.eventbrite.com/e/tidyverse-developer-day-2024-tickets-876018203027?aff=oddtdtcreator" target="_blank" rel="noopener">Buy your ticket now!</a>
</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2024/tdd-2024/thumbnail-wd.jpg" length="41628" type="image/jpeg" />
    </item>
    <item>
      <title>Survival analysis for time-to-event data with tidymodels</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-survival-analysis/</link>
      <pubDate>Wed, 03 Apr 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-survival-analysis/</guid>
      <dc:creator>Hannah Frick</dc:creator><description><![CDATA[<!--
TODO:
* [x] Look over / edit the post's title in the yaml
* [x] Edit (or delete) the description; note this appears in the Twitter card
* [x] Pick category and tags (see existing with [`hugodown::tidy_show_meta()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html))
* [x] Find photo & update yaml metadata
* [x] Create `thumbnail-sq.jpg`; height and width should be equal
* [x] Create `thumbnail-wd.jpg`; width should be >5x height
* [x] [`hugodown::use_tidy_thumbnails()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html)
* [x] Add intro sentence, e.g. the standard tagline for the package
* [x] [`usethis::use_tidy_thanks()`](https://usethis.r-lib.org/reference/use_tidy_thanks.html)
-->
<p>We&rsquo;re tickled pink to announce the support of survival analysis for time-to-event data across tidymodels. The <a href="https://www.tidymodels.org/" target="_blank" rel="noopener">tidymodels</a>
 framework is a collection of R packages for modeling and machine learning using tidyverse principles. This new support makes survival analysis a first-class citizen in tidymodels and gives censored regression modeling the same flexibility and ease as classification or regression.</p>
<p>The functionality resides in multiple tidymodels packages. The easiest way to install them all is to install the tidymodels meta-package:</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='nf'><a href='https://rdrr.io/r/utils/install.packages.html'>install.packages</a></span><span class='o'>(</span><span class='s'>"tidymodels"</span><span class='o'>)</span></span></code></pre>
</div>
<p>This blog post will highlight why this is useful, explain which additions we&rsquo;ve made to the framework, and point to several places to learn more.</p>
<p>You can see a full list of changes in the release notes:</p>
<ul>
<li><a href="https://parsnip.tidymodels.org/news/index.html#parsnip-120" target="_blank" rel="noopener">parsnip</a>
</li>
<li><a href="https://censored.tidymodels.org/news/index.html#censored-030" target="_blank" rel="noopener">censored</a>
</li>
<li><a href="https://yardstick.tidymodels.org/news/index.html#yardstick-130" target="_blank" rel="noopener">yardstick</a>
</li>
<li><a href="https://workflows.tidymodels.org/news/index.html#workflows-114" target="_blank" rel="noopener">workflows</a>
</li>
<li><a href="https://tune.tidymodels.org/news/index.html#tune-120" target="_blank" rel="noopener">tune</a>
</li>
<li><a href="https://finetune.tidymodels.org/news/index.html#finetune-120" target="_blank" rel="noopener">finetune</a>
</li>
<li><a href="https://workflowsets.tidymodels.org/news/index.html#workflowsets-110" target="_blank" rel="noopener">workflowsets</a>
</li>
</ul>
<h2 id="increasing-usefulness-two-perspectives">Increasing usefulness: Two perspectives
</h2>
<p>We&rsquo;d like to situate the changes from two different perspectives: How this is useful for people already familiar with survival analysis as well as for people already familiar with tidymodels.</p>
<p>If you are already familiar with both: Excellent, this is very much for you! Read on for more details on how these two things come together.</p>
<h3 id="adding-tidymodels-to-your-tool-kit">Adding tidymodels to your tool kit
</h3>
<p>If you are already familiar with survival analysis but maybe not tidymodels, these changes now unlock a whole framework for predictive modelling for you. It applies tidyverse principles to modeling, meaning it strives to be consistent, composable, and human-centered. The framework covers the modeling process from the initial test/train split of the data all the way to tuning various models. Along the way it offers a rich selection of preprocessing techniques, resampling schemes, and performance metrics along with safe-guards against accidental overfitting. We make the full case for tidymodels at <a href="https://www.tidymodels.org/" target="_blank" rel="noopener">tidymodels.org</a>
.</p>
<h3 id="adding-survival-analysis-to-your-tool-kit">Adding survival analysis to your tool kit
</h3>
<p>If you are already familiar with tidymodels but maybe not survival analysis, these changes let you leverage the familiar framework for an additional type of modeling problem. Survival analysis offers methods for modeling time-to-event data. While it has its roots in medical research, it has broad applications as that event of interest can be so much more than a medical outcome. Take customer churn as an example: We are interested in how long someone is a customer for and when they churn. For customers who churned, we have the complete time for which they were customers. For existing customers, we only know how long they&rsquo;ve been customers for <em>so far</em>. Such observations are called censored. So what are our modeling choices here?</p>
<p>We could look at the time and model that as a regression problem. We could look at the event status and model that as a classification problem. Both options might get us somewhere close to an answer to our original modeling question but not quite there. Censored regression models let us model an outcome that includes both aspects, the time and the event status. And with that, it can deal with both censored and uncensored observations appropriately. With this type of model, we can predict the survival time, or in more applied terms, how long someone will stay as a customer. We can also predict the probability of survival at a given time point. This lets us answer questions like &ldquo;How likely is it that this customer will churn after 3 months?&rdquo;. See which prediction types are available for which models at <a href="https://censored.tidymodels.org/" target="_blank" rel="noopener">censored.tidymodels.org</a>
.</p>
<h2 id="ch-ch-changes-whats-new-for-censored-regression">Ch-ch-changes: What&rsquo;s new for censored regression?
</h2>
<p>The main components needed for this full-fledged integration of survival analysis into tidymodels were</p>
<ul>
<li>Survival analysis models that can take censoring into account</li>
<li>Survival analysis performance metrics that can take censoring into account</li>
<li>Integrating changes required by these models and metrics into the framework</li>
</ul>
<p>For the models, parsnip gained a new mode, <code>&quot;censored regression&quot;</code>, for existing models as well as new model types such as <code>proportional_hazards()</code>. Engines for these reside in censored, the parsnip extension package for survival models. The <code>&quot;censored regression&quot;</code> mode has been around for a while and we&rsquo;ve previously shared posts on <a href="https://www.tidyverse.org/blog/2021/11/survival-analysis-parsnip-adjacent/" target="_blank" rel="noopener">our initial thoughts</a>
 and the <a href="https://www.tidyverse.org/blog/2022/08/censored-0-1-0/" target="_blank" rel="noopener">release of censored</a>
.</p>
<p>Now we&rsquo;ve added the metrics: <a href="https://yardstick.tidymodels.org/news/index.html#yardstick-130" target="_blank" rel="noopener">yardstick v1.3.0</a>
 includes new metrics for assessing censored regression models. Somewhat similar to how metrics for classification models can take class predictions or probability predictions as input, these survival metrics can take predicted survival times or predictions of survival probabilities as input.</p>
<p>The new metrics are</p>
<ul>
<li>Concordance index on the survival time via <code>concordance_survival()</code></li>
<li>Brier score on the survival probability and its integrated version via <code>brier_survival()</code> and <code>brier_survival_integrated()</code></li>
<li>ROC curve and the area under the ROC curve on the survival probabilities via <code>roc_curve_survival()</code> and <code>auc_roc_survival()</code> respectively</li>
</ul>
<p>The probability of survival is always defined <em>at a certain point in time</em>. We call that time point the <em>evaluation time</em> because it is then also the time point at which we want to evaluate model performance. Metrics that work on the survival probabilities are also called <em>dynamic metrics</em> and you can read more about them here:</p>
<ul>
<li><a href="https://www.tidymodels.org/learn/statistics/survival-metrics/" target="_blank" rel="noopener">Dynamic Performance Metrics for Event Time Data</a>
</li>
<li><a href="https://www.tidymodels.org/learn/statistics/survival-metrics-details/" target="_blank" rel="noopener">Accounting for Censoring in Performance Metrics for Event Time Data</a>
</li>
</ul>
<p>The evaluation time is also the best example to illustrate the changes necessary to the framework. Most of them were under the hood but the evaluation time is user-facing. Let&rsquo;s take a look at that.</p>
<p>While the need for evaluation times is dependent on type of metric, it is not actually specified as an argument to the metric functions. Like yardstick&rsquo;s other metrics, those take pre-made predictions as the input. So where do you specify it then?</p>
<ul>
<li>You need to specify it to directly predict survival probabilities, via <a href="https://rdrr.io/r/stats/predict.html" target="_blank" rel="noopener"><code>predict()</code></a>
 or <code>augment()</code>. We introduced the corresponding <code>eval_time</code> argument first for fitted models in <a href="https://www.tidyverse.org/blog/2023/04/censored-0-2-0/#introducing-eval_time" target="_blank" rel="noopener">parsnip and censored</a>
 and have added it now for workflows.</li>
<li>You also need to specify it for the tuning functions <code>tune_*()</code> from tune and finetune as they will predict survival probabilities as part of the tuning process.</li>
<li>Lastly, the <code>eval_time</code> argument now shows up when working with tuning/resampling results such as in <code>show_best()</code> or <code>autoplot()</code>. Those changes span the packages generating and working with resampling results: tune, finetune, and workflowsets.</li>
</ul>
<p>As we said, plenty of changes under the hood but you shouldn&rsquo;t need to notice them. Everything else should work &ldquo;as usual,&rdquo; allowing the same ease and flexibility in combining tidymodels functionality for censored regression as for classification and regression.</p>
<h2 id="the-pieces-come-together-a-case-study">The pieces come together: A case study
</h2>
<p>To see it all in action, check out the case study <a href="https://www.tidymodels.org/learn/statistics/survival-case-study/" target="_blank" rel="noopener">How long until building complaints are dispositioned?</a>
 on the tidymodels website!</p>
<p>The city of New York publishes data on complaints received by the Department of Buildings that include how long it takes for a complaint to be dealt with (&ldquo;dispositioned&rdquo;) as well as several characteristics of the complaint. The case study covers a full analysis. We start with splitting the data into test and training sets, explore different preprocessing strategies and model types via tuning, and predict with a final model. It should give you a good first impression of how to use tidymodels for predictive survival analysis.</p>
<p>We hope you&rsquo;ll find this new capability of tidymodels useful!</p>
<h2 id="acknowledgements">Acknowledgements
</h2>
<p>Many thanks to the people who contributed to our packages since their last release:</p>
<p><strong>parsnip:</strong> <a href="https://github.com/AlbanOtt2" target="_blank" rel="noopener">@AlbanOtt2</a>
, <a href="https://github.com/birbritto" target="_blank" rel="noopener">@birbritto</a>
, <a href="https://github.com/christophscheuch" target="_blank" rel="noopener">@christophscheuch</a>
, <a href="https://github.com/EmilHvitfeldt" target="_blank" rel="noopener">@EmilHvitfeldt</a>
, <a href="https://github.com/Freestyleyang" target="_blank" rel="noopener">@Freestyleyang</a>
, <a href="https://github.com/gmcmacran" target="_blank" rel="noopener">@gmcmacran</a>
, <a href="https://github.com/hfrick" target="_blank" rel="noopener">@hfrick</a>
, <a href="https://github.com/jmunyoon" target="_blank" rel="noopener">@jmunyoon</a>
, <a href="https://github.com/joscani" target="_blank" rel="noopener">@joscani</a>
, <a href="https://github.com/jxu" target="_blank" rel="noopener">@jxu</a>
, <a href="https://github.com/marcelglueck" target="_blank" rel="noopener">@marcelglueck</a>
, <a href="https://github.com/mattheaphy" target="_blank" rel="noopener">@mattheaphy</a>
, <a href="https://github.com/mesdi" target="_blank" rel="noopener">@mesdi</a>
, <a href="https://github.com/millermc38" target="_blank" rel="noopener">@millermc38</a>
, <a href="https://github.com/nipnipj" target="_blank" rel="noopener">@nipnipj</a>
, <a href="https://github.com/pgg1309" target="_blank" rel="noopener">@pgg1309</a>
, <a href="https://github.com/rdavis120" target="_blank" rel="noopener">@rdavis120</a>
, <a href="https://github.com/seb-mueller" target="_blank" rel="noopener">@seb-mueller</a>
, <a href="https://github.com/SHo-JANG" target="_blank" rel="noopener">@SHo-JANG</a>
, <a href="https://github.com/simonpcouch" target="_blank" rel="noopener">@simonpcouch</a>
, <a href="https://github.com/topepo" target="_blank" rel="noopener">@topepo</a>
, <a href="https://github.com/vidarsumo" target="_blank" rel="noopener">@vidarsumo</a>
, and <a href="https://github.com/wzbillings" target="_blank" rel="noopener">@wzbillings</a>
.</p>
<p><strong>censored:</strong> <a href="https://github.com/bcjaeger" target="_blank" rel="noopener">@bcjaeger</a>
, <a href="https://github.com/brunocarlin" target="_blank" rel="noopener">@brunocarlin</a>
, <a href="https://github.com/EmilHvitfeldt" target="_blank" rel="noopener">@EmilHvitfeldt</a>
, <a href="https://github.com/hfrick" target="_blank" rel="noopener">@hfrick</a>
, <a href="https://github.com/noahtsao" target="_blank" rel="noopener">@noahtsao</a>
, and <a href="https://github.com/tripartio" target="_blank" rel="noopener">@tripartio</a>
.</p>
<p><strong>yardstick:</strong> <a href="https://github.com/aecoleman" target="_blank" rel="noopener">@aecoleman</a>
, <a href="https://github.com/asb2111" target="_blank" rel="noopener">@asb2111</a>
, <a href="https://github.com/atsyplenkov" target="_blank" rel="noopener">@atsyplenkov</a>
, <a href="https://github.com/bgreenwell" target="_blank" rel="noopener">@bgreenwell</a>
, <a href="https://github.com/Dpananos" target="_blank" rel="noopener">@Dpananos</a>
, <a href="https://github.com/EduMinsky" target="_blank" rel="noopener">@EduMinsky</a>
, <a href="https://github.com/EmilHvitfeldt" target="_blank" rel="noopener">@EmilHvitfeldt</a>
, <a href="https://github.com/heidekrueger" target="_blank" rel="noopener">@heidekrueger</a>
, <a href="https://github.com/hfrick" target="_blank" rel="noopener">@hfrick</a>
, <a href="https://github.com/iacrowe" target="_blank" rel="noopener">@iacrowe</a>
, <a href="https://github.com/jarbet" target="_blank" rel="noopener">@jarbet</a>
, <a href="https://github.com/jxu" target="_blank" rel="noopener">@jxu</a>
, <a href="https://github.com/mattwarkentin" target="_blank" rel="noopener">@mattwarkentin</a>
, <a href="https://github.com/maxwell-geospatial" target="_blank" rel="noopener">@maxwell-geospatial</a>
, <a href="https://github.com/moloscripts" target="_blank" rel="noopener">@moloscripts</a>
, <a href="https://github.com/rdavis120" target="_blank" rel="noopener">@rdavis120</a>
, <a href="https://github.com/ruddnr" target="_blank" rel="noopener">@ruddnr</a>
, <a href="https://github.com/SimonCoulombe" target="_blank" rel="noopener">@SimonCoulombe</a>
, <a href="https://github.com/simonpcouch" target="_blank" rel="noopener">@simonpcouch</a>
, <a href="https://github.com/tbrittoborges" target="_blank" rel="noopener">@tbrittoborges</a>
, <a href="https://github.com/tonyelhabr" target="_blank" rel="noopener">@tonyelhabr</a>
, <a href="https://github.com/tripartio" target="_blank" rel="noopener">@tripartio</a>
, <a href="https://github.com/TSI-PTG" target="_blank" rel="noopener">@TSI-PTG</a>
, <a href="https://github.com/vnijs" target="_blank" rel="noopener">@vnijs</a>
, <a href="https://github.com/wbuchanan" target="_blank" rel="noopener">@wbuchanan</a>
, and <a href="https://github.com/zkrog" target="_blank" rel="noopener">@zkrog</a>
.</p>
<p><strong>workflows:</strong> <a href="https://github.com/Milardkh" target="_blank" rel="noopener">@Milardkh</a>
, <a href="https://github.com/simonpcouch" target="_blank" rel="noopener">@simonpcouch</a>
, and <a href="https://github.com/topepo" target="_blank" rel="noopener">@topepo</a>
.</p>
<p><strong>tune:</strong> <a href="https://github.com/AlbertoImg" target="_blank" rel="noopener">@AlbertoImg</a>
, <a href="https://github.com/dramanica" target="_blank" rel="noopener">@dramanica</a>
, <a href="https://github.com/EmilHvitfeldt" target="_blank" rel="noopener">@EmilHvitfeldt</a>
, <a href="https://github.com/epiheather" target="_blank" rel="noopener">@epiheather</a>
, <a href="https://github.com/hfrick" target="_blank" rel="noopener">@hfrick</a>
, <a href="https://github.com/joranE" target="_blank" rel="noopener">@joranE</a>
, <a href="https://github.com/jrosell" target="_blank" rel="noopener">@jrosell</a>
, <a href="https://github.com/jxu" target="_blank" rel="noopener">@jxu</a>
, <a href="https://github.com/kbodwin" target="_blank" rel="noopener">@kbodwin</a>
, <a href="https://github.com/kenraywilliams" target="_blank" rel="noopener">@kenraywilliams</a>
, <a href="https://github.com/KJT-Habitat" target="_blank" rel="noopener">@KJT-Habitat</a>
, <a href="https://github.com/lionel-" target="_blank" rel="noopener">@lionel-</a>
, <a href="https://github.com/marcozanotti" target="_blank" rel="noopener">@marcozanotti</a>
, <a href="https://github.com/MasterLuke84" target="_blank" rel="noopener">@MasterLuke84</a>
, <a href="https://github.com/mikemahoney218" target="_blank" rel="noopener">@mikemahoney218</a>
, <a href="https://github.com/PathosEthosLogos" target="_blank" rel="noopener">@PathosEthosLogos</a>
, <a href="https://github.com/Peter4801" target="_blank" rel="noopener">@Peter4801</a>
, <a href="https://github.com/simonpcouch" target="_blank" rel="noopener">@simonpcouch</a>
, <a href="https://github.com/topepo" target="_blank" rel="noopener">@topepo</a>
, and <a href="https://github.com/walkerjameschris" target="_blank" rel="noopener">@walkerjameschris</a>
.</p>
<p><strong>finetune:</strong> <a href="https://github.com/EmilHvitfeldt" target="_blank" rel="noopener">@EmilHvitfeldt</a>
, <a href="https://github.com/hfrick" target="_blank" rel="noopener">@hfrick</a>
, <a href="https://github.com/jdberson" target="_blank" rel="noopener">@jdberson</a>
, <a href="https://github.com/jrosell" target="_blank" rel="noopener">@jrosell</a>
, <a href="https://github.com/mfansler" target="_blank" rel="noopener">@mfansler</a>
, <a href="https://github.com/ruddnr" target="_blank" rel="noopener">@ruddnr</a>
, <a href="https://github.com/simonpcouch" target="_blank" rel="noopener">@simonpcouch</a>
, and <a href="https://github.com/topepo" target="_blank" rel="noopener">@topepo</a>
.</p>
<p><strong>workflowsets:</strong> <a href="https://github.com/dchiu911" target="_blank" rel="noopener">@dchiu911</a>
, <a href="https://github.com/hfrick" target="_blank" rel="noopener">@hfrick</a>
, <a href="https://github.com/jkylearmstrong" target="_blank" rel="noopener">@jkylearmstrong</a>
, <a href="https://github.com/PathosEthosLogos" target="_blank" rel="noopener">@PathosEthosLogos</a>
, and <a href="https://github.com/simonpcouch" target="_blank" rel="noopener">@simonpcouch</a>
.</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-survival-analysis/thumbnail-wd.jpg" length="641120" type="image/jpeg" />
    </item>
    <item>
      <title>Quarto for Reproducible Medical Manuscripts</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2024-04-01-manuscripts-rmedicine/</link>
      <pubDate>Mon, 01 Apr 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2024-04-01-manuscripts-rmedicine/</guid>
      <dc:creator>Mine Çetinkaya-Rundel</dc:creator><description><![CDATA[<p>Recently I gave a webinar for R/Medicine titled &ldquo;Quarto for Reproducible Medical Manuscripts&rdquo;. You can watch the video below or on the R Consortium website at <a href="https://www.r-consortium.org/r-medicine-quarto-for-reproducible-medical-manuscripts" target="_blank" rel="noopener">https://www.r-consortium.org/r-medicine-quarto-for-reproducible-medical-manuscripts</a>
.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>















  

  
  
  
    
    
  

  
  










  
  
    <div class="w-full aspect-video">
      <iframe
        src="https://www.youtube.com/embed/NK1onTLcgY4"
        class="w-full h-full"
        
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen></iframe>
    </div>
  




<p>Some highlights from the webinar include:</p>
<ul>
<li>
<p>Step-by-step instructions for getting started with a new manuscript project</p>
</li>
<li>
<p>Obtaining multiple formats from one source</p>
</li>
<li>
<p>An overview of the rich front matter</p>
</li>
<li>
<p>Embedding computations from supplementary notebooks</p>
<ul>
<li>Note that I demoed embedding computations in R from .qmd files however it&rsquo;s also possible to embed computations from Jupyter notebooks and computations done in Python.</li>
</ul>
</li>
<li>
<p>A live-coding demo of authoring Quarto manuscripts with RStudio and all the bells-and-whistles of the visual editor, including:</p>
<ul>
<li>cross referencing</li>
<li>citations</li>
<li>inline code</li>
</ul>
</li>
<li>
<p>Ability to actually interact with code from a manuscript with Binder</p>
</li>
<li>
<p>And a rich Q&amp;A, thanks to the audience!</p>
</li>
</ul>
<p>The slides (also written in Quarto!) and their source code can be found at the links below:</p>
<ul>
<li>
<p>Slides: <a href="https://mine.quarto.pub/quarto-manuscripts-rmed" target="_blank" rel="noopener">https://mine.quarto.pub/quarto-manuscripts-rmed</a>
</p>
</li>
<li>
<p>Source code for slides: <a href="https://github.com/mine-cetinkaya-rundel/quarto-manuscripts-rmed" target="_blank" rel="noopener">https://github.com/mine-cetinkaya-rundel/quarto-manuscripts-rmed</a>
</p>
</li>
</ul>
<p>In addition, the webinar featured a reproduction of a medical manuscript with Quarto.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Materials from this reproduction can be found at the links below:</p>
<ul>
<li>
<p>Manuscript homepage: <a href="https://mine-cetinkaya-rundel.github.io/indo-rct" target="_blank" rel="noopener">https://mine-cetinkaya-rundel.github.io/indo-rct</a>
</p>
<ul>
<li>This is an HTML page but you can also access PDF and MS Word versions of the manuscript by clicking on their respective links.</li>
<li>You can also find a link to the Binder instance for this manuscript.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></li>
</ul>
</li>
<li>
<p>Source code for manuscript: <a href="https://github.com/mine-cetinkaya-rundel/indo-rct" target="_blank" rel="noopener">https://github.com/mine-cetinkaya-rundel/indo-rct</a>
</p>
</li>
</ul>
<p>Ready to get started writing a manuscript with Quarto? Go to <a href="https://quarto.org/docs/manuscripts" target="_blank" rel="noopener">https://quarto.org/docs/manuscripts</a>
 for more info and a step-by-step tutorial. Happy authoring!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Huge thanks to the R Consortium for hosting the webinar and making the recording available so quickly!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Huge thanks to <a href="https://github.com/higgi13425" target="_blank" rel="noopener">Peter Higgins</a>
 who pointed me to this article as well as the R package that contains code from the article (<a href="https://higgi13425.github.io/medicaldata/" target="_blank" rel="noopener"><strong>medicaldata</strong></a>
) and shared some starter code with me.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>The Binder instance takes a few minutes to launch, you can leave that running in a tab while you browse the rest of the manuscript in another tab.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2024-04-01-manuscripts-rmedicine/images/manuscripts-thumbnail.png" length="113188" type="image/png" />
    </item>
    <item>
      <title>Fair machine learning with tidymodels</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-fairness/</link>
      <pubDate>Thu, 21 Mar 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-fairness/</guid>
      <dc:creator>Simon Couch</dc:creator><description><![CDATA[<p>We&rsquo;re very, very excited to announce the introduction of tools for assessing model fairness in tidymodels. This effort involved coordination from various groups at Posit over the course of over a year and resulted in a toolkit that we believe is both principled and impactful.</p>
<p>Fairness assessment features for tidymodels extend across a number of packages; to install each, use the tidymodels meta-package:</p>
<div class="highlight">
<pre class='chroma'><code class='language-r' data-lang='r'><span><span class='nf'><a href='https://rdrr.io/r/utils/install.packages.html'>install.packages</a></span><span class='o'>(</span><span class='s'>"tidymodels"</span><span class='o'>)</span></span></code></pre>
</div>
<h2 id="machine-learning-fairness">Machine learning fairness
</h2>
<p>In recent years, high-profile analyses have called attention to many contexts where the use of machine learning deepened inequities in our communities. In late 2022, a group of Posit employees across teams, roles, and technical backgrounds formed a reading group to engage with literature on machine learning fairness, a research field that aims to define what it means for a statistical model to act unfairly and take measures to address that unfairness. We then designed new software functionality and learning resources to help data scientists measure and critique the ways in which the machine learning models they&rsquo;ve built might disparately impact people affected by that model.</p>
<p>Perhaps the core question that fairness as a research field has tried to address is exactly what a machine learning model acting fairly entails. As a recent primer notes, &ldquo;[t]he rapid growth of this new field has led to wildly inconsistent motivations, terminology, and notation, presenting a serious challenge for cataloging and comparing definitions&rdquo; (Mitchell et al. 2021).</p>
<p>Broadly, approaches to fairness provide tooling&mdash;whether social or algorithmic&mdash;to understand the social implications of utilizing a machine learning model. Different researchers categorize approaches to fairness differently, but work in this area can be loosely summarized as falling into one or more of the following categories: assessment, mitigation, and critique.</p>
<ul>
<li>
<p><em>Assessment</em>: Fairness assessment tooling allows practitioners to measure the degree to which a machine learning model acts unfairly given some definition of fairness. The chosen definition of fairness greatly impacts whether a model&rsquo;s predictions are regarded as fair. While there have been many, many definitions of fairness proposed&mdash;a popular tutorial on these approaches compares 21 canonical definitions&mdash;most all of them involve simple inequalities based on a small set of conditional probabilities (Narayanan 2018; Mitchell et al. 2021).</p>
</li>
<li>
<p><em>Mitigation</em>: Given a fairness assessment, mitigation approaches reduce the degree to which a machine learning model acts unfairly given some definition of fairness. Making a model more fair according to one metric may make that model less fair according to another. Approaches to mitigation are subject to impossibility theorems, which show that &ldquo;definitions are not mathematically or morally compatible in general&rdquo; (Mitchell et al. 2021). That is, there is no way to satisfy many fairness constraints at once unless we live in a world with no inequality to start with. However, more recent studies have shown that near-fairness with respect to several definitions is quite possible (Bell et al. 2023).</p>
</li>
<li>
<p><em>Critique</em>: While approaches to assessment and mitigation seek to reduce complexity and situate notions of fairness in mathematical formalism, sociotechnical critique provides tooling to better understand how mathematical notions of fairness may fail to account for the real-world complexity of social phenomena. Work in this discipline often reveals that, in the process of measuring or addressing unfairness by some definition, methods for fairness assessment and mitigation may actually ignore, necessitate, or introduce unfairness by some other definition.</p>
</li>
</ul>
<p>The work of scoping Posit&rsquo;s resources for fair machine learning, in large part, involved striking the right balance between tools in these categories and integrating them thoughtfully among our existing functionality. Rather than supporting as many fairness-oriented tools as possible, our goal is to best enable users of our tools to reason well about the fairness-relevant decisions they make throughout the modeling process.</p>
<h2 id="additions-to-tidymodels">Additions to tidymodels
</h2>
<p>The most recent set of tidymodels releases include changes that provide support for assessment and critique using the tidymodels framework.</p>
<!-- TODO: change the tidymodels.org urls to the merged versions -->
<p>The most recent yardstick release introduces <a href="https://yardstick.tidymodels.org/reference/new_groupwise_metric.html" target="_blank" rel="noopener">a tool to create fairness metrics</a>
 with the problem context in mind, as well as <a href="https://yardstick.tidymodels.org/reference/index.html#fairness-metrics" target="_blank" rel="noopener">some outputs of that tool</a>
 implementing common fairness metrics. For a higher-level introduction to the concept of a groupwise metric, we&rsquo;ve also introduced a <a href="https://yardstick.tidymodels.org/articles/grouping.html" target="_blank" rel="noopener">new package vignette</a>
. To see those fairness metrics in action, see <a href="https://www.tidymodels.org/learn/work/fairness-detectors/" target="_blank" rel="noopener">this new article on tidymodels.org</a>
, a case study using data about GPT detectors.</p>
<p>The most recent tune release integrates support for those fairness metrics from yardstick, allowing users to evaluate fairness criteria across resamples. To demonstrate those features in context, we&rsquo;ve added <a href="https://www.tidymodels.org/learn/work/fairness-readmission/" target="_blank" rel="noopener">another new article on tidymodels.org</a>
, modeling hospital readmission for patients with Type I diabetes.</p>
<p>Notably, we haven&rsquo;t introduced functionality to support mitigation. While a number of methods have proliferated over the years to finetune models to act more fairly with respect to some fairness criteria, each apply only in relatively niche applications with modest experimental results (Agarwal et al. 2018; Mittelstadt, Wachter, and Russell 2023). For now, we believe that, in practice, the efforts of practitioners&mdash;and thus our efforts to support them&mdash;are better spent engaging with the sociotechnical context of a given modeling problem (Holstein et al. 2019).</p>
<p>We&rsquo;re excited to support modeling practitioners in fairness-oriented analysis of models and look forward to seeing how these methods are put to work.</p>
<h2 id="references">References
</h2>
<div id="refs" class="references csl-bib-body hanging-indent" entry-spacing="0">
<div id="ref-agarwal2018" class="csl-entry">
<p>Agarwal, Alekh, Alina Beygelzimer, Miroslav Dudı́k, John Langford, and Hanna Wallach. 2018. &ldquo;A Reductions Approach to Fair Classification.&rdquo; In <em>International Conference on Machine Learning</em>, 60&ndash;69. PMLR.</p>
</div>
<div id="ref-bell2023" class="csl-entry">
<p>Bell, Andrew, Lucius Bynum, Nazarii Drushchak, Tetiana Zakharchenko, Lucas Rosenblatt, and Julia Stoyanovich. 2023. &ldquo;The Possibility of Fairness: Revisiting the Impossibility Theorem in Practice.&rdquo; In <em>Proceedings of the 2023 ACM Conference on Fairness, Accountability, and Transparency</em>, 400&ndash;422. FAccT &lsquo;23. New York, NY, USA: Association for Computing Machinery. <a href="https://doi.org/10.1145/3593013.3594007" target="_blank" rel="noopener">https://doi.org/10.1145/3593013.3594007</a>
.</p>
</div>
<div id="ref-holstein2019" class="csl-entry">
<p>Holstein, Kenneth, Jennifer Wortman Vaughan, Hal Daumé III, Miro Dudik, and Hanna Wallach. 2019. &ldquo;Improving Fairness in Machine Learning Systems: What Do Industry Practitioners Need?&rdquo; In <em>Proceedings of the 2019 CHI Conference on Human Factors in Computing Systems</em>, 1&ndash;16.</p>
</div>
<div id="ref-mitchell2021" class="csl-entry">
<p>Mitchell, Shira, Eric Potash, Solon Barocas, Alexander D&rsquo;Amour, and Kristian Lum. 2021. &ldquo;Algorithmic Fairness: Choices, Assumptions, and Definitions.&rdquo; <em>Annual Review of Statistics and Its Application</em> 8 (1): 141&ndash;63. <a href="https://doi.org/10.1146/annurev-statistics-042720-125902" target="_blank" rel="noopener">https://doi.org/10.1146/annurev-statistics-042720-125902</a>
.</p>
</div>
<div id="ref-mittelstadt2023" class="csl-entry">
<p>Mittelstadt, Brent, Sandra Wachter, and Chris Russell. 2023. &ldquo;The Unfairness of Fair Machine Learning: Levelling down and Strict Egalitarianism by Default.&rdquo; <em>arXiv Preprint arXiv:2302.02404</em>.</p>
</div>
<div id="ref-narayanan2018" class="csl-entry">
<p>Narayanan, Arvind. 2018. &ldquo;Translation Tutorial: 21 Fairness Definitions and Their Politics.&rdquo; In <em>Proc. Conf. Fairness Accountability Transp., New York, Usa</em>, 1170:3.</p>
</div>
</div>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-fairness/thumbnail-wd.jpg" length="221609" type="image/jpeg" />
    </item>
    <item>
      <title>Take the tidymodels survey for 2024 priorities</title>
      <link>https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-2024-survey/</link>
      <pubDate>Wed, 28 Feb 2024 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-2024-survey/</guid>
      <dc:creator>Emil Hvitfeldt</dc:creator><description><![CDATA[<!--
TODO:
* [x] Look over / edit the post's title in the yaml
* [x] Edit (or delete) the description; note this appears in the Twitter card
* [x] Pick category and tags (see existing with [`hugodown::tidy_show_meta()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html))
* [x] Find photo & update yaml metadata
* [x] Create `thumbnail-sq.jpg`; height and width should be equal
* [x] Create `thumbnail-wd.jpg`; width should be >5x height
* [x] [`hugodown::use_tidy_thumbnails()`](https://rdrr.io/pkg/hugodown/man/use_tidy_post.html)
* [x] Add intro sentence, e.g. the standard tagline for the package
* [x] [`usethis::use_tidy_thanks()`](https://usethis.r-lib.org/reference/use_tidy_thanks.html)
-->
<p>At the end of 2021, we created a survey to get community input on how we prioritize our projects. <a href="https://colorado.posit.co/rsc/tidymodels-priorities-2022/" target="_blank" rel="noopener">The results</a>
 gave us a good sense of which items people were most interested in. Since then we have completed a number of projects:</p>
<ul>
<li><strong>Model fairness metrics</strong> were included in <a href="https://yardstick.tidymodels.org/news/index.html#yardstick-130" target="_blank" rel="noopener">yardstick 1.3.0</a>
 with <a href="https://www.tidymodels.org/" target="_blank" rel="noopener">tidymodels.org</a>
 posts coming soon.</li>
<li><strong>Spatial analysis models and methods</strong> led to the creation of <a href="https://spatialsample.tidymodels.org/" target="_blank" rel="noopener">spatialsample</a>
.</li>
<li><strong>H2O.ai support</strong> was achieved with the creation of <a href="https://agua.tidymodels.org/" target="_blank" rel="noopener">agua</a>
.</li>
<li><strong>Better serialization tools</strong> are now provided in the <a href="https://github.com/rstudio/bundle" target="_blank" rel="noopener">bundle</a>
 package.</li>
</ul>
<p>Almost everything that respondents prioritized highly last year has either been completed or is currently in progress. Our main focus right now is to wrap up survival analysis, which is being done right now with a series of CRAN releases for the affected packages. Most immediately following these releases, we will be working on postprocessing and supervised feature selection. Beyond that, we&rsquo;d like to once again ask the community for feedback to help us better prioritize features in the coming year.</p>
<h2 id="looking-toward-2024">Looking toward 2024
</h2>
<p><strong>Take a look at <a href="https://conjoint.qualtrics.com/jfe/form/SV_aWw8ocGN5aPgeZE" target="_blank" rel="noopener">our survey for next priorities</a>
</strong> and let us know what you think. There are some items we&rsquo;ve put &ldquo;on the menu&rdquo; but you can write in other items that you are interested in.</p>
<p>The current slate of our possible priorities include:</p>
<h3 id="sparse-tibbles">Sparse tibbles
</h3>
<p>Many models benefit from having sparse data, both in execution time and memory usage. We can&rsquo;t take full advantage of this since recipes use tibbles. This project would involve making it so the tibbles used <em>inside of a recipe</em> can hold sparse data. This would not be intended as a general substitute for regular tibbles.</p>
<h3 id="causal-inference-interface">Causal inference interface
</h3>
<p>While many common causal inference workflows are already possible with tidymodels, a small set of helper functions could greatly ease the experience of causal modeling in the framework. Specifically, these changes would better accommodate a two-stage modeling approach, using predictions from a propensity model to set case weights for an outcome model.</p>
<h3 id="improve-chattr">Improve chattr
</h3>
<p><a href="https://github.com/mlverse/chattr" target="_blank" rel="noopener">chattr</a>
 is an interface to large language models (LLMs). It enables interaction with the model directly from the RStudio IDE. This task would involve fine-tuning it to give better results when used for tidymodels tasks.</p>
<h3 id="cost-sensitive-learning-api">Cost-sensitive learning API
</h3>
<p>This feature is another solution for severe class imbalances. The main part of this task is making our approaches to this uniform across models.</p>
<h3 id="expand-models-for-stacking-ensembles">Expand models for stacking ensembles
</h3>
<p>As of now, the stacks package only supports combining the predictions of member models using a regularized linear model. We could extend the package to allow for combining predictions using any modeling <a href="https://workflows.tidymodels.org" target="_blank" rel="noopener">workflow</a>
.</p>
<h3 id="extend-support-for-spatial-ml">Extend support for spatial ML
</h3>
<p><a href="https://spatialsample.tidymodels.org/" target="_blank" rel="noopener">spatialsample</a>
 introduced a number of spatial resampling methods to tidymodels. More comprehensive support for spatial ML would involve better integrating <a href="https://www.mm218.dev/posts/2022-08-11-waywiser-010-is-now-on-cran/" target="_blank" rel="noopener">spatial metrics</a>
 into the framework and introducing support for new spatial model types.</p>
<h3 id="ordinal-regression-extension-package">Ordinal regression extension package
</h3>
<p>Ordinal regression models are specific to classification tasks with a natural ordering to the outcome categories (e.g., low, medium, high, etc.). We could add support for modeling this type of data in a parsnip extension package.</p>
<p><a href="https://conjoint.qualtrics.com/jfe/form/SV_aWw8ocGN5aPgeZE" target="_blank" rel="noopener">Check out our survey</a>
 and tell us what your priorities are!</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/tidyverse/2024/tidymodels-2024-survey/thumbnail-wd.jpg" length="508223" type="image/jpeg" />
    </item>
    <item>
      <title>ASA Traveling Courses on Quarto</title>
      <link>https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/</link>
      <pubDate>Tue, 05 Dec 2023 00:00:00 +0000</pubDate>
      <guid>https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/</guid>
      <dc:creator>Mine Çetinkaya-Rundel</dc:creator><description><![CDATA[<p>In 2023, <a href="https://andrewpbray.github.io/" target="_blank" rel="noopener">Dr. Andrew Bray</a>
 and I gave a series of six workshops on Quarto as part of the <a href="https://community.amstat.org/coc/chapterresources/travelingcourse" target="_blank" rel="noopener">Traveling Courses</a>
 program sponsored by the <a href="https://www.amstat.org/" target="_blank" rel="noopener">American Statistical Association</a>
.</p>
<p>The workshop was designed for those who want to take their R Markdown skills and expertise and apply them in Quarto, the next generation of R Markdown. Participants learned how to apply their reproducible authoring skills to the Quarto format and about new tools and workflows for authoring with Quarto in RStudio. The workshop covered creating static documents and presentations, building websites, and writing blogs and books. Finally, participants learned various ways to deploy and publish their Quarto projects on the web.</p>
<p>Home pages and links to source code for each of the six workshops are listed below:</p>
<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr>
<td>Nebraska Chapter<br />
Omaha, Nebraska<br />
April 28, 2023<br />
<a href="https://mine.quarto.pub/quarto-asa-nebraska/">mine.quarto.pub/quarto-asa-nebraska</a><br />
<a href="https://github.com/asa-quarto/website-nebraska/tree/nebraska-workshop">Source</a><br />
</td>
<td><a href="https://mine.quarto.pub/quarto-asa-nebraska/"><img src="https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/asa-nebraska.png" data-fig-alt="Homepage of Nebraska Chapter workshop" width="400" /></a></td>
</tr>
<tr>
<td>Oregon Chapter<br />
Portland, Oregon<br />
June 10, 2023<br />
<a href="https://andrew.quarto.pub/oregon-asa/">andrew.quarto.pub/oregon-asa</a><br />
<a href="https://github.com/andrewpbray/quarto-asa/tree/oregon-chapter">Source</a><br />
</td>
<td><a href="https://andrew.quarto.pub/oregon-asa/"><img src="https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/asa-oregon.png" data-fig-alt="Homepage of Oregon Chapter workshop" width="400" /></a></td>
</tr>
<tr>
<td>Alaska Chapter<br />
Anchorage, Alaska<br />
June 20, 2023<br />
<a href="https://andrew.quarto.pub/alaska-asa/">andrew.quarto.pub/alaska-asa/</a><br />
<a href="https://github.com/asa-quarto/website/tree/alaska-workshop">Source</a><br />
</td>
<td><a href="https://andrew.quarto.pub/alaska-asa/"><img src="https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/asa-alaska.png" data-fig-alt="Homepage of Alaska Chapter workshop" width="400" /></a></td>
</tr>
<tr>
<td>Ohio Chapter<br />
Virtual Workshop on Zoom<br />
August 18, 2023<br />
<a href="https://andrew.quarto.pub/ohio-asa/">andrew.quarto.pub/ohio-as</a><br />
<a href="https://github.com/asa-quarto/website/tree/ohio-workshop">Source</a><br />
</td>
<td><a href="https://andrew.quarto.pub/ohio-asa/"><img src="https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/asa-ohio.png" data-fig-alt="Homepage of Ohio Chapter workshop" width="400" /></a></td>
</tr>
<tr>
<td>Boston Chapter<br />
Virtual Workshop on Zoom<br />
September 20, 2023<br />
<a href="https://andrew.quarto.pub/boston-asa/">andrew.quarto.pub/boston-asa</a><br />
<a href="https://github.com/asa-quarto/website/tree/boston-workshop">Source</a><br />
</td>
<td><a href="https://andrew.quarto.pub/boston-asa/"><img src="https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/asa-boston.png" data-fig-alt="Homepage of Boston Chapter workshop" width="400" /></a></td>
</tr>
<tr>
<td>Mid-Tennessee Chapter<br />
Nashville, Tennessee<br />
October 20, 2023<br />
<a href="https://github.com/asa-quarto/website/tree/nashville-workshop">mine.quarto.pub/quarto-asa-nashville</a><br />
<a href="https://github.com/asa-quarto/website/releases/tag/nashville-workshop">Source</a><br />
</td>
<td><a href="https://mine.quarto.pub/quarto-asa-nashville/"><img src="https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/asa-mid-tennessee.png" data-fig-alt="Homepage of Mid-Tennessee Chapter workshop" width="400" /></a></td>
</tr>
</tbody>
</table>
<p>One of the Quarto features we leveraged in organizing these materials is that you can publish to different QuartoPub URLs from the same repository with <code>quarto publish</code>. After each workshop, we created a release on GitHub to take a snapshot of the materials for that workshop, and for the subsequent workshop, we made edits to the materials on the <code>main</code> branch and published them to a new URL.</p>
<p>The source code for everything can be found at <a href="https://github.com/asa-quarto/website" target="_blank" rel="noopener">github.com/asa-quarto/website</a>
. Also in the GitHub organization is a repo containing the &ldquo;your turn&rdquo; exercises for the workshops: <a href="https://github.com/asa-quarto/exercises" target="_blank" rel="noopener">github.com/asa-quarto/exercises</a>
.</p>
<p>All materials are released with Creative Commons Attribution-ShareAlike 4.0 International license. If you are teaching a Quarto workshop, feel free to reuse any and all of these materials. And if you&rsquo;re learning Quarto, you might find it helpful to follow along with any of the workshops listed above.</p>
<p>Happy learning and happy teaching!</p>
]]></description>
      <enclosure url="https://posit-open-source.netlify.app/blog/quarto/2023-12-05-asa-traveling-courses/asa-traveling-courses.png" length="1145581" type="image/png" />
    </item>
  </channel>
</rss>
