<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>3 Minutes Wednesdays</title>
    <description>Weekly bite-sized tips on DataViz, Shiny and Stats/Machine Learning.</description>
    
    <link>https://3mw.albert-rapp.de/</link>
    <atom:link href="https://rss.beehiiv.com/feeds/Ma00qoTlsO.xml" rel="self"/>
    
    <lastBuildDate>Sun, 12 Jul 2026 12:04:28 +0000</lastBuildDate>
    <pubDate>Wed, 08 Jul 2026 17:00:00 +0000</pubDate>
    <atom:published>2026-07-08T17:00:00Z</atom:published>
    <atom:updated>2026-07-12T12:04:28Z</atom:updated>
    
      <category>Programming</category>
      <category>Education</category>
      <category>Technology</category>
    <copyright>Copyright 2026, 3 Minutes Wednesdays</copyright>
    
    <image>
      <url>https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/publication/logo/dcd4eaf2-0a16-4f6e-a277-324841b39e98/Twitter_header_-_6.png</url>
      <title>3 Minutes Wednesdays</title>
      <link>https://3mw.albert-rapp.de/</link>
    </image>
    
    <docs>https://www.rssboard.org/rss-specification</docs>
    <generator>beehiiv</generator>
    <language>en-us</language>
    <webMaster>support@beehiiv.com (Beehiiv Support)</webMaster>

      <item>
  <title>Parallel LLM Chats Extract a Lot of Data All at Once</title>
  <description></description>
  <link>https://3mw.albert-rapp.de/p/parallel-llm-chats-extract-a-lot-of-data-all-at-once</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/parallel-llm-chats-extract-a-lot-of-data-all-at-once</guid>
  <pubDate>Wed, 08 Jul 2026 17:00:00 +0000</pubDate>
  <atom:published>2026-07-08T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#5f063d;border-radius:10px;margin:20.0px 20.0px 20.0px 20.0px;padding:20.0px 20.0px 20.0px 20.0px;"><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Remember how I </span><span style="color:#F9FAFB;"><span style="text-decoration:underline;"><a class="link" href="https://3mw.albert-rapp.de/p/announcing-typst-for-automated-reports?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=parallel-llm-chats-extract-a-lot-of-data-all-at-once" target="_blank" rel="noopener noreferrer nofollow" style="color: #FFFFFF">bamboozled Excel users</a></span></span><span style="color:#F9FAFB;"> with my cool PDF automation? </span></p><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">If you want to pull that off too, you can still get my </span><span style="color:#F9FAFB;"><b><span style="text-decoration:underline;"><a class="link" href="https://pdf.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=parallel-llm-chats-extract-a-lot-of-data-all-at-once" target="_blank" rel="noopener noreferrer nofollow" style="color: #F9FAFB">&quot;Report Automation With Typst&quot;</a></span></b></span><span style="color:#F9FAFB;"> course at the cheaper pre-sale price. </span></p><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">And you can get extra 10% off using the code </span><span style="color:#F9FAFB;"><b>“ITSDONE10”</b></span><span style="color:#F9FAFB;"> at checkout. Both the promo code and the pre-sale price </span><span style="color:#F9FAFB;"><b>expire on Sunday</b></span><span style="color:#F9FAFB;">.</span></p></div><p class="paragraph" style="text-align:left;">Guten Tag! 👋 </p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany.</p><p class="paragraph" style="text-align:left;">Last week we extracted data from one PDF with <code>&#123;ellmer&#125;</code>. But often we don’t want to get data out of one single PDF. Instead, we want to use multiple PDFs. Today, let’s combine <code>&#123;ellmer&#125;</code>, <code>&#123;fs&#125;</code>, <code>&#123;purrr&#125;</code> and <code>&#123;pdftools&#125;</code> to do that in one smooth pipeline. 🥳 </p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="getting-the-pdf-paths"><b>Getting the PDF paths</b></h1><p class="paragraph" style="text-align:left;">As you know, the <code>&#123;fs&#125;</code> package allows you get paths to many files in a directory. For example, I have a couple of PDFs inside a <code>pdfs/</code> directory:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/055ac4e2-d6d8-4236-a5b6-819c68836755/image.png?t=1783523142"/></div><p class="paragraph" style="text-align:left;">As you can probably guess from these paths, these are the PDF penguin reports that we generated <span style="text-decoration:underline;"><a class="link" href="https://3mw.albert-rapp.de/p/creating-beautiful-pdf-reports-with-typst-and-quarto?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=parallel-llm-chats-extract-a-lot-of-data-all-at-once" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(13, 110, 253)">a while back</a></span>. Back then, I used Quarto & Typst. But nowadays I just use Typst. In any case, that’s how one of the PDFs looks:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f92b681e-7ccb-4add-a24f-d57b71377f6e/image.png?t=1783523101"/></div><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/902ce641-a647-49d9-bb63-67d74bf3425c/image.png?t=1783523118"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="get-the-text-content-from-all-pd-fs"><b>Get the text content from all PDFs</b></h1><p class="paragraph" style="text-align:left;">Next, we can get the text content from all PDFs. The magical <code>&#123;purrr&#125;</code> package makes it really easy to apply the <code>pdftools::pdf_text()</code> function iteratively. That’s perfect to iterate over the <code>paths_pdf</code> vector we’ve just created.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/ce26b616-42c8-4e9d-95a5-e745a35a9915/image.png?t=1783523265"/></div><p class="paragraph" style="text-align:left;">This looks pretty ugly. So let’s remove all extra white spaces with <code>stringr::str_squish()</code>. Once again, we can use <code>&#123;purrr&#125;</code> to iterate over all those texts.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/95d90fa8-9948-4d93-88cf-b3b30683a361/image.png?t=1783523288"/></div><p class="paragraph" style="text-align:left;">Ahh that looks much better.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="do-many-llm-calls"><b>Do many LLM calls</b></h1><p class="paragraph" style="text-align:left;">Now, you might think that we can also use <code>&#123;purrr&#125;</code> to iterate over all these pages. And you’re right. We could. But that’s not the efficient way to do it.</p><p class="paragraph" style="text-align:left;">You see, <code>&#123;ellmer&#125;</code> allows us to run data extractions <b>in parallel</b>. We just have to pass a list of prompts to <code>parallel_chat_structured()</code>. Here’s how that looks:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/1e032fa4-a450-41ef-bc50-864f4c9ea84a/image.png?t=1783523011"/></div><p class="paragraph" style="text-align:left;">Sweet! With that we have looped over our entire content and extracted information from it. Even better, this was much faster than running 3 LLM calls one after the other. With <code>parallel_chat_structured()</code>, you will asynchronously sent a bunch of llm calls all at once.</p><p class="paragraph" style="text-align:left;">Even better: This happens all in the same R process. So you didn’t even have to think about async stuff like the things that the <code>&#123;mirai&#125;</code> package allows you to do. And <code>&#123;ellmer&#125;</code> will even take care of sending LLM calls in bits and pieces. Let me demonstrate that with the progress bar that you’ve seen above. I’ll simply repeat a bunch of my data and send more requests to the LLM:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c87d8d5e-1a9f-4ada-a7f3-5b811582c92b/image.png?t=1783522995"/></div><p class="paragraph" style="text-align:left;">Have a look how the progress bar evolves. Row-by-row <code>&#123;ellmer&#125;</code> will tell you that:</p><ul><li><p class="paragraph" style="text-align:left;">15 LLM calls are queued, 0 have to be retried, 9 calls are waiting on a reply and 6 already finished</p></li><li><p class="paragraph" style="text-align:left;">0 queued, 0 retries, 10 still waiting, 20 finished</p></li><li><p class="paragraph" style="text-align:left;">0 queued, 0 retries, 1 still waiting, 29 finished</p></li><li><p class="paragraph" style="text-align:left;">All done</p></li></ul><p class="paragraph" style="text-align:left;">So as you can see we can throw a whole bunch of data at <code>&#123;ellmer&#125;</code> and it will process that all in parallel for us. Pretty sweet, isn’t it?</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Alrighty, that was everything I wanted to cover this week. Hope you enjoyed it. Feel free to hit the reply button to tell me about how you liked this newsletter episode. </p><p class="paragraph" style="text-align:left;">And don’t forget about the <span style="text-decoration:underline;"><a class="link" href="https://pdf.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=parallel-llm-chats-extract-a-lot-of-data-all-at-once" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(13, 110, 253)">“Report Automation With Typst”</a></span> course. Offer is still available until Sunday.</p><p class="paragraph" style="text-align:left;">See you next week,<br>Albert</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Whenever you’re ready, there are three I can help you:</p><ol start="1"><li><p class="paragraph" style="text-align:left;"><b><a class="link" href="https://pdf.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=parallel-llm-chats-extract-a-lot-of-data-all-at-once" target="_blank" rel="noopener noreferrer nofollow">Automate Your Data Reports:</a></b><b> </b>This course helps data analysts eliminate manual copy-paste reporting by automating PDF reports end-to-end, saving hours every cycle and preventing costly mistakes. (Using the lovely Typst language 😍)</p></li><li><p class="paragraph" style="text-align:left;"><b><a class="link" href="https://data-cleaning.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=parallel-llm-chats-extract-a-lot-of-data-all-at-once" target="_blank" rel="noopener noreferrer nofollow">Generate Insights in Minutes, not Hours:</a></b> This comprehensive course teaches you to handle data faster, smarter, and more efficiently.</p></li><li><p class="paragraph" style="text-align:left;"><b>Bespoke Data Science Solutions: </b>I’ve helped clients build their own data science solutions. Whether building custom web apps, PDF reports, AI automations or teaching workshops, I’ve got you covered. You can reach out to me via <a class="link" href="https://workwithalbert.carrd.co/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=parallel-llm-chats-extract-a-lot-of-data-all-at-once" target="_blank" rel="noopener noreferrer nofollow">this form </a>(or simply hit reply to this email)</p></li></ol></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=9919b752-7bba-451f-89be-db7c76238f0e&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Announcing: Typst for Automated Reports</title>
  <description></description>
  <link>https://3mw.albert-rapp.de/p/announcing-typst-for-automated-reports</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/announcing-typst-for-automated-reports</guid>
  <pubDate>Mon, 06 Jul 2026 17:00:00 +0000</pubDate>
  <atom:published>2026-07-06T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Guten Tag! 👋 </p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany.</p><p class="paragraph" style="text-align:left;">Last week I gave a talk in front of like 50 actuaries who mostly deal with Excel to wrangle data. My task was to show them the tools of the trade that data scientists like to use to wrangle data. So naturally this meant talking about programming to an audience that isn’t too keen about programming (as they mostly use Excel.)</p><p class="paragraph" style="text-align:left;">Luckily for me I had a special treat with me. You see, I also had slides about Typst. Now, you may wonder why would a non-programmer audience suddenly be excited about Typst!?</p><p class="paragraph" style="text-align:left;">But here’s the thing: I didn’t just talk about Typst. What I actually talked about was <b>automating reports</b> <i>using Typst combined with R or Python</i>.</p><p class="paragraph" style="text-align:left;">As you’d expect, everyone in the room was familiar with the process of</p><ul><li><p class="paragraph" style="text-align:left;">crunching numbers,</p></li><li><p class="paragraph" style="text-align:left;">copying that over to Word,</p></li><li><p class="paragraph" style="text-align:left;">and then printing that as a PDF.</p></li></ul><p class="paragraph" style="text-align:left;">And of course everyone knows how annoying and error prone this process is.</p><p class="paragraph" style="text-align:left;">So that’s why I could see so many people become excited about the promise to automatically generate reports from data. Especially after I showed them that this PDF is also generated automatically:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fcdc4db7-0453-4bc7-aa12-b55543d7dc19/image.png?t=1783280457"/></div><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/dabd02bb-1a21-4b1e-89de-a853fc097a41/image.png?t=1783280492"/></div><p class="paragraph" style="text-align:left;">That’s the power of Typst. Not only can it generate PDFs, it can also baffle a non-programmer audience with its skills for working with data and automating tedious processes. How cool is that?</p><p class="paragraph" style="text-align:left;">So that’s why I’m super excited to share that I have finally recorded the video that walks you through how to generate the above PDF. The video will be edited later this week.</p><p class="paragraph" style="text-align:left;">That’s why this announcement is a heads-up: I am about to take my <span style="text-decoration:underline;"><a class="link" href="https://pdf.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=announcing-typst-for-automated-reports" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(13, 110, 253)">“Report Automation With Typst”</a></span> course from pre-sale mode into its final form.</p><p class="paragraph" style="text-align:left;">This will also remove the pre-sale discount that is currently available. So you can still get the full course at pre-sale price before I increase the price on <b>Sunday, July 12</b>. </p><p class="paragraph" style="text-align:left;">And even better: I’m adding a <i>“it’s finally done”</i> discount to the current pre-sale price. Use the code “<b>ITSDONE10</b>” at checkout to get 10% off the pre-sale price (meaning the discount will also be gone on Sunday.)</p><p class="paragraph" style="text-align:left;">If you’ve been on the fence about the course, this is the moment to jump in. Once the video is live and the price goes up, this deal is gone for good. So if you’re ready to automatically generate PDFs from data, you can learn how to do that here:</p><div class="button" style="text-align:center;"><a target="_blank" rel="noopener nofollow noreferrer" class="button__link" style="" href="https://pdf.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=announcing-typst-for-automated-reports"><span class="button__text" style=""> Learn PDF automation </span></a></div><p class="paragraph" style="text-align:left;">Best,<br>Albert</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Whenever you’re ready, there are three I can help you:</p><ol start="1"><li><p class="paragraph" style="text-align:left;"><b><a class="link" href="https://pdf.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=announcing-typst-for-automated-reports" target="_blank" rel="noopener noreferrer nofollow">Automate Your Data Reports:</a></b><b> </b>This course helps data analysts eliminate manual copy-paste reporting by automating PDF reports end-to-end, saving hours every cycle and preventing costly mistakes. (Using the lovely Typst language 😍)</p></li><li><p class="paragraph" style="text-align:left;"><b><a class="link" href="https://data-cleaning.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=announcing-typst-for-automated-reports" target="_blank" rel="noopener noreferrer nofollow">Generate Insights in Minutes, not Hours:</a></b> This comprehensive course teaches you to handle data faster, smarter, and more efficiently.</p></li><li><p class="paragraph" style="text-align:left;"><b>Bespoke Data Science Solutions: </b>I’ve helped clients build their own data science solutions. Whether building custom web apps, PDF reports, AI automations or teaching workshops, I’ve got you covered. You can reach out to me via <a class="link" href="https://workwithalbert.carrd.co/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=announcing-typst-for-automated-reports" target="_blank" rel="noopener noreferrer nofollow">this form </a>(or simply hit reply to this email)</p></li></ol></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=2c264732-83a0-4cc1-9faa-75e7dcf6eeeb&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Working with non-tabular files</title>
  <description>How to work with files and extract the texts from them before passing that to an LLM for AI-assisted document processing.</description>
  <link>https://3mw.albert-rapp.de/p/working-with-non-tabular-files</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/working-with-non-tabular-files</guid>
  <pubDate>Wed, 01 Jul 2026 17:00:00 +0000</pubDate>
  <atom:published>2026-07-01T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;"></p><p class="paragraph" style="text-align:left;">Guten Tag! 👋 </p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. Last time we talked about {ellmer} and chat objects. Now, let&#39;s figure out how to do work with documents. You know, so that we can do AI-assisted document processing. </p><p class="paragraph" style="text-align:left;">Unfortunately, data scientists are often great at wrangling tabular data like tibbles or dataframes. But data scientists don&#39;t necessarily know how to deal with file formats. That was one reason why my data cleaning masterclass had one part solely focused on how to deal with different file formats. Still, that focused on files containing tabular data. </p><p class="paragraph" style="text-align:left;">In our new scenario, things are a bit different. We don&#39;t want to get a tabular file format into an LLM. Instead, we want to work with arbitrary text files like PDFs or Word documents or other file formats. And there are two ingredients for this. First, there is the file management part and then there’s the text extraction part. Let&#39;s talk about them both today.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="file-management">File management</h1><p class="paragraph" style="text-align:left;">There are many functions inside R that allow you to manage files. But I feel like the <code>&#123;fs&#125;</code> package gives you a more consistent interface. Basically, the functions come in three flavors for files, paths and directories. The functions start with <code>file_*</code> , <code>path_*</code> or <code>dir_*</code> respectively:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a1538546-4f22-40fb-85e8-85ba13d36251/image.png?t=1782885067"/><div class="image__source"><span class="image__source_text"><p>Examples mostly taken from the {fs} documentation</p></span></div></div><p class="paragraph" style="text-align:left;">This allows you to manage files effectively through a consistent, unified interface. And yes, I know how incredibly boring this sounds. But it becomes really convenient when you have to deal with many files. So, if you want to learn more about that, I’ve released a video that goes into more details about <code>&#123;fs&#125;</code>: </p><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="true" class="youtube_embed" frameborder="0" height="100%" src="https://youtube.com/embed/EfHVYXqIuJ4" width="100%"></iframe><hr class="content_break"><h1 class="heading" style="text-align:left;" id="text-extraction">Text Extraction</h1><p class="paragraph" style="text-align:left;">Once you know how to manage files, you can extract texts from them. For most use cases, you’ll need texts from PDF. For that, there is the <code>&#123;pdftools&#125;</code> package. If we had an invoice stored at <code>dat/invoice.pdf</code> we could access the text like so:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c623ea45-552e-4994-b0b7-abe9e0fdb7a9/image.png?t=1782885153"/></div><p class="paragraph" style="text-align:left;">For Word documents, you could use the <code>&#123;officer&#125;</code> package. It allows you to first extract the content elements in a structured form:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fcd40a77-c1a2-4ac0-89cc-f634171356ef/image.png?t=1782885177"/></div><p class="paragraph" style="text-align:left;">And if you filter that for paragraphs, then you’d get only the texts:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/291f32d4-891d-49a9-b0fe-071be40e6198/image.png?t=1782885190"/></div><p class="paragraph" style="text-align:left;">Of course, once you have the raw text, you can apply one or more of the many text cleaning functions that the <code>&#123;stringr&#125;</code> package provides you. That&#39;s particularly useful if you&#39;re looking to add or subtract specific information that can be encoded programmatically before passing the content to an LLM. Feel free to check out <a class="link" href="https://stringr.tidyverse.org?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=working-with-non-tabular-files" target="_blank" rel="noopener noreferrer nofollow">the </a><code>&#123;stringr&#125;</code><a class="link" href="https://stringr.tidyverse.org?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=working-with-non-tabular-files" target="_blank" rel="noopener noreferrer nofollow"> docs</a> or my <a class="link" href="https://data-cleaning.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=working-with-non-tabular-files" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a> for more on text cleaning.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">That was it for today. For simple text extractions, you&#39;ve got the tools you need now. If you want to go even further, you could do an OCR using a service like Azure Document Intelligence or AWS Textract. But that’s a story for some other time.</p><p class="paragraph" style="text-align:left;">Best,<br>Albert</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Whenever you’re ready, there are three I can help you:</p><ol start="1"><li><p class="paragraph" style="text-align:left;"><b><a class="link" href="https://pdf.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=working-with-non-tabular-files" target="_blank" rel="noopener noreferrer nofollow">Automate Your Data Reports:</a></b><b> </b>This course helps data analysts eliminate manual copy-paste reporting by automating PDF reports end-to-end, saving hours every cycle and preventing costly mistakes. (Using the lovely Typst language 😍)</p></li><li><p class="paragraph" style="text-align:left;"><b><a class="link" href="https://data-cleaning.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=working-with-non-tabular-files" target="_blank" rel="noopener noreferrer nofollow">Generate Insights in Minutes, not Hours:</a></b> This comprehensive course teaches you to handle data faster, smarter, and more efficiently.</p></li><li><p class="paragraph" style="text-align:left;"><b>Bespoke Data Science Solutions: </b>I’ve helped clients build their own data science solutions. Whether building custom web apps, PDF reports, AI automations or teaching workshops, I’ve got you covered. You can reach out to me via <a class="link" href="https://workwithalbert.carrd.co/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=working-with-non-tabular-files" target="_blank" rel="noopener noreferrer nofollow">this form </a>(or simply hit reply to this email)</p></li></ol></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=0dd1b8bf-e6b6-428f-bd51-6292a810497a&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Can we actually bring AI automations into production?</title>
  <description></description>
  <link>https://3mw.albert-rapp.de/p/can-we-actually-bring-ai-automations-into-production</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/can-we-actually-bring-ai-automations-into-production</guid>
  <pubDate>Wed, 24 Jun 2026 17:00:00 +0000</pubDate>
  <atom:published>2026-06-24T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Guten Tag! 👋 </p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. I see more and more data scientist being thrown into loosely data-related activities. The reason for that is (of course) AI. Ugh. </p><p class="paragraph" style="text-align:left;">Yes, AI is the gift that keeps on giving. And if you&#39;re anything like me, you probably have a love and hate relationship with AI. It is such a super cool tool and I use it every day. But the hype around it is just maddening. </p><p class="paragraph" style="text-align:left;">Aaaannnyway, the reason for why I&#39;m writing about AI here is because data people are being thrown into the deep engineering end. </p><p class="paragraph" style="text-align:left;"><i>“It&#39;s related to data”</i>, they said. “<i>So it must be a good task for data scientists”</i>, they said. </p><p class="paragraph" style="text-align:left;">Well, over the last three years I’ve been building AI-powered automations. You know, the (by now) classical automation that </p><ul><li><p class="paragraph" style="text-align:left;">takes in a document, </p></li><li><p class="paragraph" style="text-align:left;">extracts all the data that is desired and then </p></li><li><p class="paragraph" style="text-align:left;">passes the structured data along to clients or some other part of the company. </p></li></ul><p class="paragraph" style="text-align:left;">That is a cool thing to work on. I love the automations that come out of this.</p><p class="paragraph" style="text-align:left;">But time and time again, I realized that the tasks that come with building such an automation are not really what data scientists learn in their training. </p><p class="paragraph" style="text-align:left;">But don’t fret. Let’s just change that. </p><p class="paragraph" style="text-align:left;">Over the next couple of weeks I want to give you a high level overview of what it can entail to bring an AI document extraction into production.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="revisiting-the-ai-basics">Revisiting the AI basics</h1><p class="paragraph" style="text-align:left;">If you’ve been a long time reader, you know that long ago I published a little Quarto book called <a class="link" href="https://air.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=can-we-actually-bring-ai-automations-into-production" target="_blank" rel="noopener noreferrer nofollow">“R with AI”</a>. In there, I explained how to use the <code>&#123;ellmer&#125;</code> package to use AI from R. And just like meeting the love of your life, it can all start with a simple chat:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/baff96d9-63bd-45f1-9256-342e89b4686b/image.png?t=1781898224"/></div><p class="paragraph" style="text-align:left;">Unlike the love of your life, AI keeps asks you for an API key. So the above code only works if you have an <code>ANTHROPIC_API_KEY</code> <a class="link" href="https://3mw.albert-rapp.de/p/environment-variables-in-r?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=can-we-actually-bring-ai-automations-into-production" target="_blank" rel="noopener noreferrer nofollow">environment variable</a>. With this chat, you can call one of its methods to talk to the AI. Like so:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/11cf6c8f-25bf-4d37-8fe4-c6095124fd44/image.png?t=1781898209"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="so-how-about-structured-data-extrac">So how about structured data extraction?</h1><p class="paragraph" style="text-align:left;">Luckily for us, ellmer also makes it very easy to extract data from the text we give it. All we have to do is use the <code>chat_structured()</code> method of the chat. This in combination with </p><ul><li><p class="paragraph" style="text-align:left;">some text to extract from and </p></li><li><p class="paragraph" style="text-align:left;">a specification of what to extract </p></li></ul><p class="paragraph" style="text-align:left;">will get the job done. The latter is done by chaining/nesting many <code>type_*()</code> functions to establish elaborate structures to extract. Here, we’re just going to extract all the numbers we can find by combining <code>type_number()</code> with <code>type_array()</code> </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b0c87256-62ab-4c88-baa0-64a793489bff/image.png?t=1781898184"/></div><p class="paragraph" style="text-align:left;">Note that the <code>description</code> that you see inside <code>type_*()</code> functions are the prompts for the things you want to extract.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="lets-do-one-more">Lets do one more</h1><p class="paragraph" style="text-align:left;">By combining <code>type_array()</code> and <code>type_object()</code> we can let the AI extract data.frames. In this case, it allows us to avoid regular expressions:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5c7e1155-a211-41ca-aa66-767261ae134f/image.png?t=1781898163"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">Cool. So AI allows us to avoid writing regular expressions. Revolutionary stuff!</p><p class="paragraph" style="text-align:left;">But in all serious, this is a pretty powerful mechanism. So it’s no wonder that I got to spent the last couple of years building automations around this stuff. More on that next time.</p><p class="paragraph" style="text-align:left;">Best,<br>Albert</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Whenever you’re ready, there are three I can help you:</p><ol start="1"><li><p class="paragraph" style="text-align:left;"><b><a class="link" href="https://pdf.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=can-we-actually-bring-ai-automations-into-production" target="_blank" rel="noopener noreferrer nofollow">Automate Your Data Reports:</a></b><b> </b>This course helps data analysts eliminate manual copy-paste reporting by automating PDF reports end-to-end, saving hours every cycle and preventing costly mistakes. (Using the lovely Typst language 😍)</p></li><li><p class="paragraph" style="text-align:left;"><b><a class="link" href="https://data-cleaning.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=can-we-actually-bring-ai-automations-into-production" target="_blank" rel="noopener noreferrer nofollow">Generate Insights in Minutes, not Hours:</a></b> This comprehensive course teaches you to handle data faster, smarter, and more efficiently.</p></li><li><p class="paragraph" style="text-align:left;"><b>Bespoke Data Science Solutions: </b>I’ve helped clients build their own data science solutions. Whether building custom web apps, PDF reports, AI automations or teaching workshops, I’ve got you covered. You can reach out to me via <a class="link" href="https://workwithalbert.carrd.co/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=can-we-actually-bring-ai-automations-into-production" target="_blank" rel="noopener noreferrer nofollow">this form </a>(or simply hit reply to this email)</p></li></ol></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=ec744a2e-a829-4fca-958a-a2390cb1e30f&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>What R users struggle with</title>
  <description></description>
  <link>https://3mw.albert-rapp.de/p/what-r-users-struggle-with</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/what-r-users-struggle-with</guid>
  <pubDate>Sun, 14 Jun 2026 15:28:32 +0000</pubDate>
  <atom:published>2026-06-14T15:28:32Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Guten Tag! 👋 </p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. In my last mail, I announced that I&#39;m working on a workshop to bring more technical content into the R community. </p><p class="paragraph" style="text-align:left;">And wow. Many of you had thoughts on that. </p><p class="paragraph" style="text-align:left;">Turns out, I hit a nerve when I said that there are too few resources on bringing R into production. But not in a bad way. Your responses were more like “Yes, exactly! This is what I&#39;ve been looking for.”</p><p class="paragraph" style="text-align:left;">So I&#39;m glad that I wasn&#39;t imagining things. And I&#39;m also glad that there&#39;s an interest in this community to close many of these technical gaps.</p><p class="paragraph" style="text-align:left;">Not surprisingly, most responses were about two things:</p><ol start="1"><li><p class="paragraph" style="text-align:left;">How to work (more efficiently) with databases and cloud storage.</p></li><li><p class="paragraph" style="text-align:left;">How to use functional and functional object oriented programming to write more robust R code.</p></li></ol><p class="paragraph" style="text-align:left;">And this doesn&#39;t surprise me because both things are real struggles that you hit immediately when working in a business setting. Also, the fact that there&#39;s a high demand for such a fundamental building block only underlines my initial assessment: R users are often left alone to figure out how to operate their favorite language in business settings.</p><p class="paragraph" style="text-align:left;">So this only strengthens my resolve to teach an online workshop on some of these more technical topics. Details to follow. In the meantime, you can check out my newest YT video on how to connect your favorite data science language to databases, cloud storage or APIs:</p><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="true" class="youtube_embed" frameborder="0" height="100%" src="https://youtube.com/embed/XRI3Vl_LiSM" width="100%"></iframe><p class="paragraph" style="text-align:left;">Best,<br>Albert</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Whenever you’re ready, there are three I can help you:</p><ol start="1"><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://pdf.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=what-r-users-struggle-with" target="_blank" rel="noopener noreferrer nofollow"><b>Automate Your Data Reports:</b></a><b> </b>This course helps data analysts eliminate manual copy-paste reporting by automating PDF reports end-to-end, saving hours every cycle and preventing costly mistakes.</p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=what-r-users-struggle-with" target="_blank" rel="noopener noreferrer nofollow"><b>Generate Insights in Minutes, not Hours:</b></a> This comprehensive course teaches you to handle data faster, smarter, and more efficiently.</p></li><li><p class="paragraph" style="text-align:left;"><b>Bespoke Data Science Solutions: </b>I’ve helped clients build their own data science solutions. Whether that’s building custom web apps, PDF reports, AI automations or teaching workshops, I’ve got you covered. You can reach out to me via <a class="link" href="https://workwithalbert.carrd.co/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=what-r-users-struggle-with" target="_blank" rel="noopener noreferrer nofollow">this form </a>(or simply hit reply to this email)</p></li></ol></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=05803d99-3e57-4d66-8666-ecf8e8f7a216&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Using Database Transactions in R)</title>
  <description>Database transactions should be your default mode of writing data to a database. In this newsletter, I show you how these transactions work in R.</description>
  <link>https://3mw.albert-rapp.de/p/using-database-transactions-in-r</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/using-database-transactions-in-r</guid>
  <pubDate>Wed, 09 Jul 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-07-09T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul><p class="paragraph" style="text-align:left;">Or use my affiliate code <b>“RAPP10” to get 10% off </b>the fantastic data science courses from Athlyticz:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://athlyticz.com/affiliate-courses?am_id=rapp10&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank" rel="noopener noreferrer nofollow">State of the Art Data Science Training</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. In today’s newsletter, I want to teach you about <b>database transactions</b>. Sounds simple, but it’s actually a very crucial concept that we haven’t covered before.</p><p class="paragraph" style="text-align:left;">You see, in many cases you’ll want to write to your database using transactions. Technically, you could just write to your database as-is. But this leaves you <b>without any safety precautions in case something goes wrong</b>.</p><p class="paragraph" style="text-align:left;">For example, you could lose your internet connection in the middle of uploading a large dataset. If that happens your database ends up with only part of the data, and then you’re stuck trying to figure out:</p><ul><li><p class="paragraph" style="text-align:left;">What was successfully transferred?</p></li><li><p class="paragraph" style="text-align:left;">What’s still only on your local machine?</p></li></ul><p class="paragraph" style="text-align:left;">These kinds of situations can easily leave your database in a broken or inconsistent state. And that’s really really frustrating to deal with.</p><p class="paragraph" style="text-align:left;">So that’s where <b>transactions</b> come in. Let’s dive in.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="what-are-transactions"><b>What Are Transactions?</b></h1><p class="paragraph" style="text-align:left;">Transactions allow you to tell your database ahead of time</p><p class="paragraph" style="text-align:left;"><i>“Hey, I’m going to write something. I’ll let you know when I’m done. Don’t finalize anything until I say so.”</i></p><p class="paragraph" style="text-align:left;">If everything works fine, you “commit” the transaction, and the data gets saved. If not, you “roll it back,” and it’s like nothing ever happened.</p><p class="paragraph" style="text-align:left;">Sounds simple, right? Well, it is. You just have to use this nifty little safety feature. Your database will thank you.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="how-to-use-transactions-in-r"><b>How to Use Transactions in R</b></h1><p class="paragraph" style="text-align:left;">It’s surprisingly easy to use transactions in R when working with databases. You start a transaction with:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/dae90a3a-f826-4c6f-8f2b-baa181fab88b/image.png?t=1750768790"/></div><p class="paragraph" style="text-align:left;">Then, you perform your usual data writing operations. Let’s assume we’re just going to add a few rows:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/59a8becd-5832-4634-a4b8-e116a209b118/image.png?t=1750768798"/></div><p class="paragraph" style="text-align:left;">If everything goes well, you finalize the changes with:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/79c6c9f9-2789-410e-8ef4-d8ce09e2d87b/image.png?t=1750768807"/></div><p class="paragraph" style="text-align:left;">Or if anything goes wrong, you can cancel the whole transaction, i.e. everything you did since you called <code>dbBegin()</code>:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9f53b816-3afa-4171-8431-ab512757482d/image.png?t=1750768815"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="why-is-this-helpful"><b>Why Is This Helpful?</b></h1><p class="paragraph" style="text-align:left;">This is especially useful when you’re working with <b>multiple tables</b>.</p><p class="paragraph" style="text-align:left;">Let’s say you need to insert data into one table and then into another table that references the first table. Let’s try this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/18fe6e87-c47c-4e97-be7e-b9b0e93281fc/image.png?t=1750768831"/></div><p class="paragraph" style="text-align:left;">Notice how the second call failed? That happened because I put restrictions on the second table whereas the first one doesn’t have them.</p><p class="paragraph" style="text-align:left;">Either way, that’s when we call <code>dbRollback()</code>. And in order for all of this to happen automatically, we can wrap the whole procedure into a <code>tryCatch()</code> statement.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/218ce6a2-21ab-4885-8e22-3473e4179bee/image.png?t=1750768872"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">And with that, you’ve got a new set of tools to interact with databases <b>safely and reliably</b>. Use transactions whenever you write to a database, especially when multiple related operations are involved. Your future self (and your data) will thank you!</p><p class="paragraph" style="text-align:left;">And as always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-database-transactions-in-r" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=e38e2d2a-383d-4986-b585-312f8c4a3ec7&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Writing SQL in R Efficiently)</title>
  <description>I show you how to assemble SQL code from within R using the glue_sql() function from the {glue} package. Much simpler and safer than using paste()!</description>
  <link>https://3mw.albert-rapp.de/p/writing-sql-in-r-efficiently</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/writing-sql-in-r-efficiently</guid>
  <pubDate>Wed, 02 Jul 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-07-02T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul><p class="paragraph" style="text-align:left;">Or use my affiliate code <b>“RAPP10” to get 10% off </b>the fantastic data science courses from Athlyticz:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://athlyticz.com/affiliate-courses?am_id=rapp10&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank" rel="noopener noreferrer nofollow">State of the Art Data Science Training</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. The <code>glue_sql()</code> function helped us last week to make our database calls safer and avoid SQL injection.</p><p class="paragraph" style="text-align:left;">But there’s also a lot of convenience that <code>glue_sql()</code> offers for everyday development. So let’s check that out.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="use-curly-braces-for-r-variables"><b>Use Curly Braces for R Variables</b></h1><p class="paragraph" style="text-align:left;">The first thing that’s really convenient and that you already know from last week is this: You can use curly braces <code>&#123;&#125;</code> inside your SQL string to insert R variables. This works great when the variables are just simple strings or scalar values.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2b7a7785-ec4f-4b36-be0f-c8c64654a0a6/image.png?t=1750766863"/></div><p class="paragraph" style="text-align:left;">And as you can see, this gives you the results you probably want:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e62baad3-59ac-49f2-a903-9eac587304ea/image.png?t=1750766873"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="use-backticks-for-i-ds"><b>Use Backticks for IDs</b></h1><p class="paragraph" style="text-align:left;">Next, let’s try to not grab all columns but only a selected one:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/bd62319f-d77b-437e-92a9-6fe9c9f01487/image.png?t=1750766900"/></div><p class="paragraph" style="text-align:left;">Well, that didn’t crash but it didn’t go as expected either. The reason for that is that you will have to tell <code>glue_sql()</code> that <code>col_name</code> (and technically also <code>tbl_name</code>) is an ID. You can do that with backticks <b>inside</b> the curly brackets.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f24145dc-3c28-40c7-be69-c9a7ce5dff21/image.png?t=1750766910"/></div><p class="paragraph" style="text-align:left;">Ahh this looks much better!</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="collapse-vectors-with-the-operator"><b>Collapse Vectors with the </b><code>*</code><b> Operator</b></h1><p class="paragraph" style="text-align:left;">If you pass a vector into a placeholder, <code>glue_sql()</code> by default tries to insert the whole vector resulting in multiple SQL fragments:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3ea4dedc-8c44-48ba-9b52-c652f4cb21f3/image.png?t=1750766920"/></div><p class="paragraph" style="text-align:left;">This is usually <b>not</b> what you want. Instead, you want to collapse a vector with <code>*</code>:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/67ef4f8c-a6c9-4078-a567-dccb7930f85f/image.png?t=1750766927"/></div><p class="paragraph" style="text-align:left;">Sweet! With that you can easily get data from multiple columns:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/bb030609-ed8b-4fb5-becc-9e9a21e7fdef/image.png?t=1750766936"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="use-i-ds-from-different-tables"><b>Use IDs from different tables</b></h1><p class="paragraph" style="text-align:left;">Let’s imagine that our database has another table:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/72d20d91-0833-4e9f-8fc1-bb88f42eb7d5/image.png?t=1750766947"/></div><p class="paragraph" style="text-align:left;">Then, we can make sure to reference to columns from different tables by including the table names. The <code>Id()</code> function helps with that:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/340e3bf6-e4b9-4d51-9e18-40c84e719eac/image.png?t=1750766958"/></div><p class="paragraph" style="text-align:left;">And because we need to identify the corrsponding species columns somehow, we have to reference to the corresponding table names as well.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c9116161-2a0a-48c8-befa-208b9a118efa/image.png?t=1750766972"/></div><p class="paragraph" style="text-align:left;">Now, we could easily wrap all of these IDs into backticks and everything works out nicely in assembled SQL code. Here’s an example from the <code>glue_sql()</code> docs for that:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/33c586d2-d9cb-4917-87fb-dc03520c6bdf/image.png?t=1750766986"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">And there you have it: <code>glue_sql()</code> will make your life as an R developer much easier. Beyond just protecting you from SQL injection, it helps you write cleaner, more flexible, and maintainable database queries from within R.</p><p class="paragraph" style="text-align:left;">And as always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-writing-sql-in-r-efficiently" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=a2dae720-5834-4abe-b1eb-21c6cf910e28&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Safer SQL in R)</title>
  <description>I show you how to use the glue_sql() function from the {glue} R package to save yourself from SQL injections. That way, your database calls are much safer.</description>
  <link>https://3mw.albert-rapp.de/p/safer-sql-in-r</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/safer-sql-in-r</guid>
  <pubDate>Wed, 25 Jun 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-06-25T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul><p class="paragraph" style="text-align:left;">Or use my affiliate code <b>“RAPP10” to get 10% off </b>the fantastic data science courses from Athlyticz:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://athlyticz.com/affiliate-courses?am_id=rapp10&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank" rel="noopener noreferrer nofollow">State of the Art Data Science Training</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. In the last couple of newsletters, we talked about SQL databases. And there’s no way we can talk about accessing SQL databases via R code without mentioning <b>SQL injection</b>.</p><p class="paragraph" style="text-align:left;">This is a nasty thing that can leak data or even destroy your database if you allow people to interact with it unsafely. And often, that’s exactly what you want (the interaction, not the unsafe part 😆). Here’s a common scenario for that:</p><ul><li><p class="paragraph" style="text-align:left;">Users interact with a Shiny dashboard to retrieve specific data from a database.</p></li><li><p class="paragraph" style="text-align:left;">Based on the inputs, you execute some SQL.</p></li><li><p class="paragraph" style="text-align:left;">Your dashboard displays the new data.</p></li></ul><p class="paragraph" style="text-align:left;">So letting users interact with a database is not bad in itself. It’s only bad when you do it uncontrolled. That’s when this bad SQL injection can occur.</p><p class="paragraph" style="text-align:left;">But here’s the good news: There’s an easy way to avoid damage. And even better: This method also makes it much easier to assemble SQL code in R.</p><p class="paragraph" style="text-align:left;">Let me show you how that works.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="sql-injection-via-r-variables"><b>SQL Injection via R Variables</b></h1><p class="paragraph" style="text-align:left;">Let’s talk about how you might encounter SQL injection in the first place.</p><p class="paragraph" style="text-align:left;">Let’s imagine that you want to retrieve data about a specific penguin species from a table in your database. One common (but <b>unsafe</b>) way to do this is to paste together SQL code manually with R variables:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b515d3a9-006c-41d9-b277-eb50118936b9/image.png?t=1750766589"/></div><p class="paragraph" style="text-align:left;">While this works, it’s insecure. If a user-supplied value like <code>species</code> contains malicious SQL code, it could complete your SQL snippet <i>and</i> do something dangerous (e.g. extracting all of your confidential data). This is <b>SQL injection</b>.</p><p class="paragraph" style="text-align:left;">And in this specific scenario, here’s what that would look like. Let’s first set up our data base from last time:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5a37adb6-910b-422c-a1aa-401ae2d1fa78/image.png?t=1750766602"/></div><p class="paragraph" style="text-align:left;">And then we can stick in some malicious code into the <code>species</code> variable.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3b6474a8-81a3-4a1e-82b7-abb6462033f9/image.png?t=1750766614"/></div><p class="paragraph" style="text-align:left;">Here, a little trick was used to close the “WHERE” statement with a <code>&#39;</code> followed by an or-statement that is always true. That way, we will never actually filter the data.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="why-would-that-happen"><b>Why Would That Happen?</b></h1><p class="paragraph" style="text-align:left;">Now, you might wonder: <i>Why would my variable ever be filled with something malicious?</i></p><p class="paragraph" style="text-align:left;">Well, consider a Shiny app that allows users to filter database results. If you’re not careful, users can input harmful values into the fields that populate those SQL variables. If someone with bad intentions figures out you’re pasting user input into SQL strings, they could inject destructive SQL.</p><p class="paragraph" style="text-align:left;">And they don’t even have to do that manually. There are automated tools that try out loads of combinations in the hopes that at some point some SQL injection works.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="the-solution-glue-sql-from-glue"><b>The Solution: </b><code>glue_sql()</code><b> from </b><code>&#123;glue&#125;</code></h1><p class="paragraph" style="text-align:left;">Here’s where <code>&#123;glue&#125;</code> and its <code>glue_sql()</code> function come in. Using <code>glue_sql()</code> makes assembling SQL both easier and safer. You still write your SQL code in text form, but you use curly braces (<code>&#123;&#125;</code>) to insert variables.</p><p class="paragraph" style="text-align:left;">Most importantly, <code>glue_sql()</code> handles <b>SQL escaping</b> for you to prevent SQL injection. Here’s an example:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e5816cd0-6ac5-439e-8a89-8fff65740492/image.png?t=1750766626"/></div><p class="paragraph" style="text-align:left;">So in the standard case everything works like you’d expect. And in case there’s the same malicious code from before inside the <code>species</code> variable?</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9cd45c43-84b7-4fc1-be20-911f47850bb5/image.png?t=1750766641"/></div><p class="paragraph" style="text-align:left;">Here, <code>glue_sql()</code> will put <b>everything</b> into quotes. That way, a user cannot stick in something to close the initial quotation mark. And the resuls would be empty:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/254c77af-9423-4478-bfcb-7fd9bcbc5edb/image.png?t=1750766654"/></div><p class="paragraph" style="text-align:left;">Thus, this is easy to write <b>and</b> secure.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Fantastic! We’ve just seen how <code>glue_sql()</code> helps you write safer SQL code. But there’s more! In the next newsletter, we’ll explore additional features of <code>glue_sql()</code> that make it even more powerful.</p><p class="paragraph" style="text-align:left;">And as always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-safer-sql-in-r" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=495cad43-5bb8-4c75-8342-ce29b6de820a&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW ({dbplyr} combines the best of R &amp; SQL)</title>
  <description>I show you how to avoid using pure SQL code and instead use dplyr functions to interact with databases from within R. </description>
  <link>https://3mw.albert-rapp.de/p/dbplyr-combines-the-best-of-r-sql</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/dbplyr-combines-the-best-of-r-sql</guid>
  <pubDate>Wed, 04 Jun 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-06-04T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul><p class="paragraph" style="text-align:left;">Or use my affiliate code <b>“RAPP10” to get 10% off </b>the fantastic data science courses from Athlyticz:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://athlyticz.com/affiliate-courses?am_id=rapp10&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank" rel="noopener noreferrer nofollow">State of the Art Data Science Training</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. Last week, I showed you how to connect to databases with R. And I also mentioned that it’s helpful to write a bit more SQL code than just grabbing all the data and processing it locally. This might sound like a lot of effort, though. So here’s the good news:</p><p class="paragraph" style="text-align:left;">If you’re already using <code>dplyr</code> for data wrangling, you can get the best of both worlds. You can write <code>dplyr</code> code and let R translate that into SQL so that time-saving and resource-efficient calculations happen in the database. Then, you only retrieve the results.</p><p class="paragraph" style="text-align:left;">So in today’s newsletter I’ll show you how that works. Let’s go!</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="getting-started-with-dbplyr"><b>Getting Started with </b><code>&#123;dbplyr&#125;</code></h1><p class="paragraph" style="text-align:left;">First things first: you’ll need to install the <code>&#123;dbplyr&#125;</code> package. This package extends <code>dplyr</code> so it can translate R code into SQL syntax for supported databases.</p><p class="paragraph" style="text-align:left;"><br>To get started, establish a connection to your database using <code>DBI::dbConnect()</code>, just like before. This part hasn’t changed.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3980cc03-a8c9-412e-be2b-3e758549ee9a/image.png?t=1749051952"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="working-with-tables-using-dbplyr"><b>Working with Tables Using </b><code>&#123;dbplyr&#125;</code></h1><p class="paragraph" style="text-align:left;">Now you can use <code>&#123;dbplyr&#125;</code> functions to interact with the database using familiar <code>dplyr</code> verbs. For example, in our example database, you can copy an R dataset like <code>palmerpenguins::penguins</code> into a database table using <code>copy_to()</code>:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/10e3cf6c-c437-47bd-b455-10234ba209f6/image.png?t=1749051966"/></div><p class="paragraph" style="text-align:left;">Fun fact: Notice that I never loaded {dbplyr} 😮 {dplyr} will detect when you want to use a {dbplyr} function.</p><p class="paragraph" style="text-align:left;">Once the data is in the database, you can reference it with <code>tbl()</code>. This will <b>connect</b> to the table in the database (which is why the <code>con</code> variable is needed.)</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/0c2288f1-a165-4727-9305-5261c22f15cf/image.png?t=1749051998"/></div><p class="paragraph" style="text-align:left;">Notice how the output almost looks like a regular tibble. The only difference is that it shows only a preview and not the full dataset. And in case you’re wondering: That’s a good thing. You never know how large the database is and often a preview will suffice.</p><hr class="content_break"><p class="paragraph" style="text-align:left;"></p><div class="section" style="background-color:#e4ebf0;margin:0.0px 40.0px 0.0px 40.0px;padding:0.0px 0.0px 0.0px 0.0px;"><h1 class="heading" style="text-align:left;">Click to Support 👇️ </h1><p class="paragraph" style="text-align:left;">Hey friends 👋 I’m experimenting with ads in my newsletter to finance all the free stuff I give away. If you enjoy this newsletter and want to support it, a click on the the ad below would be a super simple but effective way to do so. 🤗 </p><p class="paragraph" style="text-align:left;"><b>No need to sign up. A click is enough support</b> 🥳 </p><hr class="content_break"><h3 class="heading" style="text-align:left;" id="youve-never-experienced-business-ne">You’ve never experienced business news like this.</h3><div class="image"><a class="image__link" href="https://www.morningbrew.com/subscribe?utm_campaign={{publication_alphanumeric_id}}&utm_medium=paid_newsletter&utm_source=beehiiv&_bhiiv=opp_ae05c30d-d159-458e-8091-a4602f0273c8_fbd824b6&bhcl_id=4a6f7506-4e23-4fcf-83bf-7d82b8824d3c_{{subscriber_id}}_{{email_address_id}}" rel="noopener" target="_blank"><img class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a8ec3269-6f0b-4531-b518-08f34409091a/Option_2.png?t=1748535894"/></a></div><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.morningbrew.com/subscribe?utm_campaign={{publication_alphanumeric_id}}&utm_medium=paid_newsletter&utm_source=beehiiv&_bhiiv=opp_ae05c30d-d159-458e-8091-a4602f0273c8_fbd824b6&bhcl_id=4a6f7506-4e23-4fcf-83bf-7d82b8824d3c_{{subscriber_id}}_{{email_address_id}}" target="_blank" rel="noopener noreferrer nofollow">Morning Brew</a> delivers business news the way busy professionals want it — quick, clear, and written like a human.</p><p class="paragraph" style="text-align:left;">No jargon. No endless paragraphs. Just the day’s most important stories, with a dash of personality that makes them surprisingly fun to read.</p><p class="paragraph" style="text-align:left;">No matter your industry, Morning Brew’s daily email keeps you up to speed on the news shaping your career and life—in a way you’ll actually enjoy.</p><p class="paragraph" style="text-align:left;">Best part? It’s 100% free. <a class="link" href="https://www.morningbrew.com/subscribe?utm_campaign={{publication_alphanumeric_id}}&utm_medium=paid_newsletter&utm_source=beehiiv&_bhiiv=opp_ae05c30d-d159-458e-8091-a4602f0273c8_fbd824b6&bhcl_id=4a6f7506-4e23-4fcf-83bf-7d82b8824d3c_{{subscriber_id}}_{{email_address_id}}" target="_blank" rel="noopener noreferrer nofollow">Sign up in 15 seconds</a>, and if you end up missing the long, drawn-out articles of traditional business media, you can always go back.</p><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.morningbrew.com/subscribe?utm_campaign={{publication_alphanumeric_id}}&utm_medium=paid_newsletter&utm_source=beehiiv&_bhiiv=opp_ae05c30d-d159-458e-8091-a4602f0273c8_fbd824b6&bhcl_id=4a6f7506-4e23-4fcf-83bf-7d82b8824d3c_{{subscriber_id}}_{{email_address_id}}" target="_blank" rel="noopener noreferrer nofollow">Check it out</a></p><hr class="content_break"><p class="paragraph" style="text-align:left;">Alright, now back to the good stuff. </p><p class="paragraph" style="text-align:left;"></p></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="writing-sql-through-dplyr-verbs"><b>Writing SQL Through </b><code>dplyr</code><b> Verbs</b></h1><p class="paragraph" style="text-align:left;">Now that you have a table-like object, you can use familiar <code>dplyr</code> verbs to generate SQL queries. For example:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2c523331-8fcf-4784-bc59-100006ce0c7c/image.png?t=1749052034"/></div><p class="paragraph" style="text-align:left;">Again, this only shows a preview. To pull the full result set from the database, use <code>collect().</code></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/217a53b4-8a46-4b38-81b9-2abf63ed9258/image.png?t=1749052044"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="seeing-the-generated-sql"><b>Seeing the Generated SQL</b></h1><p class="paragraph" style="text-align:left;">And if you’re ever wondering how <code>&#123;dbplyr&#125;</code> translated your <code>dplyr</code> code into SQL, you can inspect it using <code>show_query().</code></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3920df4c-5c98-4737-be61-e0db13374dfa/image.png?t=1749052055"/></div><p class="paragraph" style="text-align:left;">Also, this is a great way to learn more about SQL by seeing how familiar R code maps to SQL commands.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Nice. We’ve learned a simple way to interact with databases using familiar syntax. However, using <code>&#123;dbplyr&#125;</code> doesn’t mean you’ll never need to write raw SQL again. </p><p class="paragraph" style="text-align:left;">It helps you get started quickly and efficiently, though. Next week, I’ll show you how to combine <code>&#123;dbplyr&#125;</code> with raw SQL for more advanced database workflows. </p><p class="paragraph" style="text-align:left;">And as always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-dbplyr-combines-the-best-of-r-sql" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=8c174980-994f-4b75-989f-05b9743f3655&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Database Connections With R)</title>
  <description>I&#39;ll show you how to connect your R session to a SQL database so that you can get the data in a structured way.</description>
  <link>https://3mw.albert-rapp.de/p/database-connections-with-r</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/database-connections-with-r</guid>
  <pubDate>Wed, 28 May 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-05-28T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul><p class="paragraph" style="text-align:left;">Or use my affiliate code <b>“RAPP10” to get 10% off </b>the fantastic data science courses from Athlyticz:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://athlyticz.com/affiliate-courses?am_id=rapp10&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank" rel="noopener noreferrer nofollow">State of the Art Data Science Training</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. When you’re working in a company, chances are you won’t be handed a simple CSV file to work with. Instead, you’ll likely need to grab your data from a company-wide SQL database hosted in the cloud or on internal servers.</p><p class="paragraph" style="text-align:left;">So in today’s newsletter, I’ll show you how to connect to these databases using R.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="what-the-heck-is-a-driver"><b>What The Heck is a Driver?</b></h1><p class="paragraph" style="text-align:left;">First, we need a so-called driver. In simple terms, this is the tool that handles the connection between your computer and the database. Think of it as a translator that often comes in one of two flavors:</p><ul><li><p class="paragraph" style="text-align:left;"><b>ODBC drivers</b>: These drivers work with the open database connection format</p></li><li><p class="paragraph" style="text-align:left;"><b>JDBC drivers</b>: These drivers use Java (that’s what the “J” stands for in JDBC)</p></li></ul><p class="paragraph" style="text-align:left;">Here, we’ll use the <code>&#123;odbc&#125;</code> package to go down the ODBC route.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="which-driver-do-you-need"><b>Which Driver Do You Need?</b></h1><p class="paragraph" style="text-align:left;">So now that we know that we want ODBC drivers, we also need to decide which specific driver we need. You see, this kind of thing depends on the database your or your company uses. For example it could be an Oracle or PostgreSQL database that will need an Oracle or PostgreSQL driver</p><p class="paragraph" style="text-align:left;">Typically, your tech department will tell you what you need. Your job is only to understand the big picture that I’m trying to explain here.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="example-setting-up-an-sq-lite-datab"><b>Example: Setting Up an SQLite Database</b></h1><p class="paragraph" style="text-align:left;">For today’s example, we’ll simulate a database using <b>SQLite</b>, which supports in-memory databases. This means that we can simply spin up a temporary database locally on our computer.</p><p class="paragraph" style="text-align:left;">After having installed a SQLite driver for your computer, you can set up a connection from R to a temporary database using <code>&#123;DBI&#125;</code> and <code>&#123;odbc&#125;</code>:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fe69436a-2556-4d15-9b1a-6abf54c5592f/image.png?t=1746469282"/></div><p class="paragraph" style="text-align:left;">Whooah. That’s a lot of function arguments. Once again, the connection details (like database name, user, password and port) is something that your tech department should have ready for you.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="creating-and-populating-a-table"><b>Creating and Populating a Table</b></h1><p class="paragraph" style="text-align:left;">So now that we have a database connection stored in a variable called <code>con</code>, we can create a table in our SQLite database. Here, we’ll use the famous Palmer Penguins dataset:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/0e4798d9-9cab-4d9a-90d3-ab4831391266/image.png?t=1746469294"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="querying-data-from-the-database"><b>Querying Data from the Database</b></h1><p class="paragraph" style="text-align:left;">To fetch data, you’ll use <code>dbGetQuery()</code> from the <code>&#123;DBI&#125;</code> package. Here’s how to select all rows using SQL code:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a1e2af9f-e02c-4af8-b996-02f441a0e463/image.png?t=1746469310"/></div><p class="paragraph" style="text-align:left;">Alternatively, you can (and probably should) use a bit more SQL to filter down the data that you actually want.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/96c32e8a-823f-45de-acbf-dfaf1af5c4f1/image.png?t=1746469321"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="why-use-sql-for-filtering"><b>Why Use SQL for Filtering?</b></h1><p class="paragraph" style="text-align:left;">And you may wonder: <i>“Why should I invest time into learning SQL when I can just grab the full data using the snippet you’ve just shown?“</i> And indeed, you could download the entire table and filter it inside of R. But filtering directly in the database is often <b>much faster</b> because:</p><ul><li><p class="paragraph" style="text-align:left;">SQL databases are optimized for these operations</p></li><li><p class="paragraph" style="text-align:left;">You avoid transferring large datasets over the network</p></li></ul><p class="paragraph" style="text-align:left;">Learning a few basic SQL keywords can go a long way in improving your data workflow.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Nice! With that we covered:</p><ul><li><p class="paragraph" style="text-align:left;">The basics of database connections in R</p></li><li><p class="paragraph" style="text-align:left;">The difference between ODBC and JDBC</p></li><li><p class="paragraph" style="text-align:left;">How to set up and query a database using <code>&#123;DBI&#125;</code> and <code>&#123;odbc&#125;</code></p></li></ul><p class="paragraph" style="text-align:left;">Armed with these skills, you’ll hopefully be ready to connect to real company databases and work with large-scale data. As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-database-connections-with-r" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=59653b36-7f6d-47b1-a813-04e7a1104eb1&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Environment Variables in R)</title>
  <description>The three most common ways to set environment variables in R. This sounds super boring and it is. But it is not as tricky as lots of R users think at first.</description>
  <link>https://3mw.albert-rapp.de/p/environment-variables-in-r</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/environment-variables-in-r</guid>
  <pubDate>Wed, 21 May 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-05-21T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. Environment variables control <b>system-wide</b> or <b>session-wide settings</b> inside your R session. This sounds incredibly boring. And, honestly, it kind of is. </p><p class="paragraph" style="text-align:left;">But it can <b>feel complicated</b> to R users who haven’t encountered them before. When you do bump into environment variables “in the wild,” they can seem unnecessarily tricky.</p><p class="paragraph" style="text-align:left;">That’s why, in today’s newsletter, I’ll cover a bit of the mundane stuff. That is, I’ll show you how to set and get environment variables in R. I know: Exciting! So let’s dive in.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="when-do-environment-variables-matte"><b>When Do Environment Variables Matter?</b></h1><p class="paragraph" style="text-align:left;">Let’s quickly look at a couple of <b>real-world examples</b> where environment variables show up in R workflows:</p><h3 class="heading" style="text-align:left;" id="using-ap-is-like-open-ai"><b>Using APIs (like OpenAI)</b></h3><p class="paragraph" style="text-align:left;">If you’re working with APIs, such as using the <code>&#123;ellmer&#125;</code> package to connect to ChatGPT or other AI services, you’ll need to store your <b>API keys</b> as environment variables.</p><p class="paragraph" style="text-align:left;">For example, to use OpenAI’s API, you need to specify the environment variable <code>OPENAI_API_KEY</code>. This keeps your credentials <b>secure</b> and avoids hard-coding sensitive infos into your scripts.</p><h3 class="heading" style="text-align:left;" id="deploying-shiny-apps"><b>Deploying Shiny Apps</b></h3><p class="paragraph" style="text-align:left;">If you’re deploying a Shiny app, you might want to keep <b>different settings</b> for:</p><ul><li><p class="paragraph" style="text-align:left;">Production (the live version of your app that your users see)</p></li><li><p class="paragraph" style="text-align:left;">Development (the version of the app that you as a developer see and use to test new features)</p></li></ul><p class="paragraph" style="text-align:left;">Environment variables let you <b>switch configurations</b> easily depending on your deployment stage (without editing the core code.)</p><p class="paragraph" style="text-align:left;">So with the examples out of the way, let’s dive into <b>three popular methods</b> for setting environment variables.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="method-1-rprofile-my-favorite"><b>Method 1: </b><code>.Rprofile</code><b> (My Favorite)</b></h1><p class="paragraph" style="text-align:left;">The <code>.Rprofile</code> file allows you to run <b>R code automatically at the start of each R session</b>. If your project doesn’t have such a file, just create a text file and name it <code>.Rprofile</code>. And to set an environment variable, you can use <code>Sys.setenv()</code> inside the <code>.Rprofile</code> file:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/dab6f1ad-833e-4ec6-889b-e17ca7945396/image.png?t=1746469368"/></div><p class="paragraph" style="text-align:left;">🚨 <b>NOTE</b>: Only use <code>Sys.setenv()</code> inside your <code>.Rprofile</code>. If you put it in a regular script, it might get saved to your R history file. And if that ever gets pushed to a public repo, your API key could be compromised.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="method-2-renviron"><b>Method 2: </b><code>.Renviron</code></h1><p class="paragraph" style="text-align:left;">The <code>.Renviron</code> file is <b>simpler</b>. Unlike <code>.Rprofile</code>, it <b>cannot execute R code</b> as it only holds <b>key-value pairs</b>. But just like <code>.RProfile</code>, these environment variables are always loaded at the start of an R session. </p><p class="paragraph" style="text-align:left;">The file itself always follows the syntax <code>key=value</code>. Here’s an example:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/cf631f3a-ef05-480b-9c34-1b7649018922/image.png?t=1746469377"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="method-3-env-via-dotenv"><b>Method 3: </b><code>.env</code><b> (via </b><code>&#123;dotenv&#125;</code><b>)</b></h1><p class="paragraph" style="text-align:left;">The <code>.env</code> file is popular in many programming languages (like Python). A <code>.env</code> file looks just like <code>.Renviron</code>. The difference is only that you load the <code>.env</code> file manually. In R, you can use the <code>&#123;dotenv&#125;</code> package to do that.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/12a6652c-8895-42fc-af8c-3dc16f7258ca/image.png?t=1746469400"/></div><p class="paragraph" style="text-align:left;"></p><p class="paragraph" style="text-align:left;">This method is especially handy if you want to share environment variables<b> across R and Python</b>.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">There you have it. Three ways to work with environment variables in R:</p><p class="paragraph" style="text-align:left;">1️⃣ <code>.Rprofile</code> (using <code>Sys.setenv()</code>)<br>2️⃣ <code>.Renviron</code> (key-value only)<br>3️⃣ <code>.env</code> (loaded via <code>&#123;dotenv&#125;</code>)</p><p class="paragraph" style="text-align:left;">Sure, it’s not the flashiest topic but it’s super important once you move into production-like environments or need to store secrets. As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-environment-variables-in-r" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=7c22c1d6-0ff9-472b-ab7b-589552b753a2&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Parameterized Sections With Quarto)</title>
  <description>We use Quarto and parameterized reports to fill a single document with multiple similar sections that use the same code logic but different data.</description>
  <link>https://3mw.albert-rapp.de/p/parameterized-sections-with-quarto</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/parameterized-sections-with-quarto</guid>
  <pubDate>Wed, 14 May 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-05-14T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul><p class="paragraph" style="text-align:left;">Or use my affiliate code <b>“RAPP10” to get 10% off </b>the fantastic data science courses from Athlyticz:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://athlyticz.com/affiliate-courses?am_id=rapp10&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank" rel="noopener noreferrer nofollow">State of the Art Data Science Training</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. In today’s newsletter, I’ll show you how to <b>integrate multiple parametric report sections into a single report</b>. You see, instead of generating <b>separate reports</b> for each dataset, you can include multiple sections where each sections uses different data.</p><p class="paragraph" style="text-align:left;">This could look something like this:</p><ul><li><p class="paragraph" style="text-align:left;">📄 General intro text (applies to all datasets)</p></li><li><p class="paragraph" style="text-align:left;">🐟 Section A (Dataset A)</p></li><li><p class="paragraph" style="text-align:left;">🐦 Section B (Dataset B)</p></li><li><p class="paragraph" style="text-align:left;">🦋 Section C (Dataset C)</p></li><li><p class="paragraph" style="text-align:left;">✅ General conclusion</p></li></ul><p class="paragraph" style="text-align:left;">So let’s see how to build this.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="step-1-start-with-a-parametric-repo"><b>Step 1: Start with a Parametric Report</b></h1><p class="paragraph" style="text-align:left;">Begin with a <b>standard parametric report</b>, just like you normally would.</p><p class="paragraph" style="text-align:left;">For example, let’s say you have the Quarto file from last time that generates a report for a <b>single species</b>. This was driven by a <code>species</code> and a <code>color</code> parameter in the YAML header:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/89543df1-8790-4a1e-8fcd-2f61d9d8246e/image.png?t=1746468441"/></div><p class="paragraph" style="text-align:left;">This report works fine on its own, but we want to reuse the code and text within the report <b>multiple times in a single document</b>.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="step-2-create-a-main-quarto-file"><b>Step 2: Create a Main Quarto File</b></h1><p class="paragraph" style="text-align:left;">Next, create a <b>new Quarto file</b> that will act as the main document. This file will include first some general intro text, followed by multiple <b>“includes”</b> of your parametric report. For example, the document could start like this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9ae99a48-4920-4177-b4d1-dae090d0c2c4/image.png?t=1746468451"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="step-3-use-include-snippets"><b>Step 3: Use </b><code>include</code><b> Snippets</b></h1><p class="paragraph" style="text-align:left;">Quarto has a special feature that lets you include other Quarto files using the following syntax:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/ba60e3ff-b30c-4be3-9dd0-af76bfd48335/image.png?t=1746468465"/></div><p class="paragraph" style="text-align:left;">Here, this will include text and code chunks from the Quarto file <code>species_report.qmd</code>. That way, you could modify your main Quarto file like this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b619b258-248f-4d91-9cf1-7b5564f195fa/image.png?t=1746468476"/></div><p class="paragraph" style="text-align:left;">But if you render this now, you’ll hit an error that will say that <code>params</code> is not defined. If you recall, <code>params</code> is the object that we use inside the species Quarto file.</p><p class="paragraph" style="text-align:left;">Normally, this object is created from the parameters that are specifies inside the YAML header. But here this doesn’t work because <b>includes don’t copy the YAML header</b> from the included file.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="step-4-define-params-in-the-master-"><b>Step 4: Define </b><code>params</code><b> in the Master File</b></h1><p class="paragraph" style="text-align:left;">To solve this, define the <code>params</code> object manually in a code chunk <b>before</b> each include. For example, your report could look like this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c530fc87-351d-4501-8d07-7f41d65d5fb4/image.png?t=1746468488"/></div><p class="paragraph" style="text-align:left;">That way, the copied-and-pasted code from <code>species_report.qmd</code> will work because it is preceded by a code chunk that defines <code>params</code>.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="step-5-repeat-for-multiple-datasets"><b>Step 5: Repeat for Multiple Datasets</b></h1><p class="paragraph" style="text-align:left;">Now, you can repeat the same process to include multiple sections, each with a different dataset:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2a281bd7-8614-4927-8ad2-266eaceddbf6/image.png?t=1746468506"/></div><p class="paragraph" style="text-align:left;">This reuses the same species report over and over, but with different <code>params</code> each time. Super efficient, isn’t it?</p><hr class="content_break"><p class="paragraph" style="text-align:left;">This approach allows you to </p><ul><li><p class="paragraph" style="text-align:left;">reuse the same report structure,</p></li><li><p class="paragraph" style="text-align:left;">render multiple sections with different data, and</p></li><li><p class="paragraph" style="text-align:left;">produce a <b>single, polished document</b></p></li></ul><p class="paragraph" style="text-align:left;">It’s a powerful pattern when working with multiple datasets that need similar analysis! Pretty neat, right? As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-parameterized-sections-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=12f24c58-0396-4c4c-a29d-2dc808350477&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Custom Styles with Typst and Quarto)</title>
  <description>We add a bit of visual polish to a PDF file that was generated with Quarto and Typst. That way, we explore lots of possibilities of how to style PDFs with Typst.</description>
  <link>https://3mw.albert-rapp.de/p/creating-beautiful-pdf-reports-with-typst-and-quarto-170a</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/creating-beautiful-pdf-reports-with-typst-and-quarto-170a</guid>
  <pubDate>Wed, 07 May 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-05-07T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul><p class="paragraph" style="text-align:left;">Or use my affiliate code <b>“RAPP10” to get 10% off </b>the fantastic data science courses from Athlyticz:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://athlyticz.com/affiliate-courses?am_id=rapp10&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">State of the Art Data Science Training</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. In this week’s newsletter, we’re continuing our journey with <b>Typst + Quarto</b>. As promised, we’re taking our PDF reports to the next level with some <b>visual polish</b>.</p><p class="paragraph" style="text-align:left;">Today, I want to show you how to:</p><ol start="1"><li><p class="paragraph" style="text-align:left;">Add a <b>vertical color bar</b> along the left margin of every page</p></li><li><p class="paragraph" style="text-align:left;">Wrap your <b>main title</b> in a colored box and shift it slightly to the left for a bold visual effect</p></li></ol><p class="paragraph" style="text-align:left;">These small touches can improve the look and feel of your report. And once you know how these things work, you can work out how to add more visual elements with Typst.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="add-a-vertical-color-bar-to-the-lef"><b>Add a Vertical Color Bar to the Left Margin</b></h1><p class="paragraph" style="text-align:left;">Let’s start by giving all pages a distinctive look using a colored stripe along the left-hand side. To do this, we modify the <code>set page()</code> section of our Typst template. You know, this part here:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8cb3a5ec-4061-4924-9653-e325ec3c47ac/image.png?t=1743424235"/></div><p class="paragraph" style="text-align:left;">Here, we can use the <code>background</code> property with the <code>place()</code> function to overlay a rectangle:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2f063bd7-84e0-4b53-aa22-f1d605b48e13/image.png?t=1743424248"/></div><p class="paragraph" style="text-align:left;">And with this simple change, we’ve added a vertical splash of color to every page.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2fcb5b99-2ada-425d-9b8f-7ec34ef46701/ksnip_20250331-131726.png?t=1743424351"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="style-the-main-title-with-a-colored"><b>Style the Main Title with a Colored Box</b></h1><p class="paragraph" style="text-align:left;">Next, let us give our report title more visual weight. Instead of plain text, we’ll wrap it in a <b>colored box</b>. We do so by wrapping our <code>text()</code> function into a <code>box()</code> function. That way, our previous pages specification</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/ff8aea0f-2354-4677-b2a0-629cc6a60dc9/image.png?t=1743424263"/></div><p class="paragraph" style="text-align:left;">becomes</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/80878f39-52d5-463f-82c3-37647ed27708/image.png?t=1743424286"/></div><p class="paragraph" style="text-align:left;">Now, our document looks like this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4a7cc724-d0ee-4ca5-9001-b4a71f03333d/ksnip_20250331-131727.png?t=1743424365"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="shift-the-title-box"><b>Shift the title box</b></h1><p class="paragraph" style="text-align:left;">Finally, we can shift the title box slightly to the left by adding a bit of negative horizontal space.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f113f9fa-b989-415b-8063-a020d0fe7e14/image.png?t=1743424303"/></div><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b8db477b-c7be-4fca-aacf-86a56e2e83ac/ksnip_20250331-131730.png?t=1743424375"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">With just a few small tweaks, we now have a PDF report that is not only <b>parameterized</b> with different inputs but it also <b>looks polished and professional</b>.</p><p class="paragraph" style="text-align:left;">And as always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-custom-styles-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=a2d79d79-f30e-4c4c-99fa-b4ee4ec73080&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Creating Beautiful PDF Reports with Typst and Quarto)</title>
  <description>I show you how to leverage the Typst framework with Quarto to customize the styling of your PDFs really easily.</description>
  <link>https://3mw.albert-rapp.de/p/creating-beautiful-pdf-reports-with-typst-and-quarto</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/creating-beautiful-pdf-reports-with-typst-and-quarto</guid>
  <pubDate>Wed, 30 Apr 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-04-30T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. Have you ever heard of the <b>Typst</b> project? It is a lightweight, Markdown-inspired language designed for creating beautiful, customized PDF documents with minimal effort. </p><p class="paragraph" style="text-align:left;">Basically, it is supposed to be like LaTeX but muuuch easier. And the coolest part? You can use Typst <b>from within Quarto</b> to create stunning PDF reports.</p><p class="paragraph" style="text-align:left;">So in today’s newsletter, I’ll walk you through how to style our PDF document from last week. Let’s dive in</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="set-typst-as-your-pdf-format"><b>Set Typst as Your PDF Format</b></h1><p class="paragraph" style="text-align:left;">To start using Typst from Quarto, go into your <code>.qmd</code> file and specify <code>typst</code> as the output format in the YAML header:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/89edaa7c-32b9-4eb2-9363-4fc831165d2d/image.png?t=1743423454"/></div><p class="paragraph" style="text-align:left;">If you render this now, you’ll get a similar PDF output as before.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7cd2565a-a6a2-402a-9047-f10b18d23f75/image.png?t=1743423844"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="add-custom-styling-with-typst-templ"><b>Add Custom Styling with Typst Templates</b></h1><p class="paragraph" style="text-align:left;">To make our PDF look good, we’ll use <b>template partials</b> provided by Typst. There are two key files that we need to mention in the YAML header for that:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4ba75c1a-4cc4-4670-a4b6-bd2040a82bea/image.png?t=1744011227"/></div><p class="paragraph" style="text-align:left;">Both are plain text files that you can create by just taking a <code>.txt</code> file and changing the extension to <code>.typ</code>. So the more important question is: <i>“How do we fill these files?”</i> Let’s go through both files.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="filling-typstshowtyp"><b>Filling </b><code>typst-show.typ</code></h1><p class="paragraph" style="text-align:left;">This file defines the variables that are passed into the layout, such as the title, author, and parameters from your Quarto YAML. You see, what you you define in the Quarto YAML header isn’t automatically known to Typst. That’s why you need to transfer it. For that you use the <code>#show</code> function from Typst.</p><p class="paragraph" style="text-align:left;">There, you specify that your “article” layout (that’s the default name of the used layout) is equipped with a set of variables.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9194ff9f-51f9-4c69-9d4e-013fd1ff6315/image.png?t=1743423479"/></div><p class="paragraph" style="text-align:left;">The syntax takes some getting used to. Basically, you always write</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f3c3e186-5b39-4045-b260-2758c7be755f/image.png?t=1743423489"/></div><p class="paragraph" style="text-align:left;">Yeah, I know. As I said, it takes some getting used to. And for drilling down nested YAML structures, you can just use a dot symbol (<code>.</code>). With that we know enough Typst code to transfer <code>title</code>, <code>author</code> and <code>params.species</code> from our Quarto YAML header to Typst.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/573d7dc3-7a55-4666-a9db-5e4eaf6a70be/image.png?t=1743423500"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="filling-typsttemplatetyp"><b>Filling </b><code>typst-template.typ</code></h1><p class="paragraph" style="text-align:left;">Nice. One file down, one more to go.</p><p class="paragraph" style="text-align:left;">In the <code>typst-template.typ</code> file, we define the actual <b>article layout</b> of our PDF report. For that, we use the <code>#let</code> function.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8d12f428-dd08-480b-9f14-7cd839787708/image.png?t=1743423521"/></div><p class="paragraph" style="text-align:left;">Inside the function body (indicated by <code>&#123;&#125;</code>), we can now set attributes of</p><ul><li><p class="paragraph" style="text-align:left;"><code>document</code> (contains metadata),</p></li><li><p class="paragraph" style="text-align:left;"><code>text</code> (defines text properties of the document), and</p></li><li><p class="paragraph" style="text-align:left;"><code>page</code> (defines the properties of every page in the document).</p></li></ul><p class="paragraph" style="text-align:left;">Have a look at the code and see if you can make out what it does. I like to think that it’s somewhat manageable to piece together what it does. But don’t worry. I’ll explain afterwards anyway.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/24595bbc-469d-45cb-a28e-7bd19fa3d461/image.png?t=1743423549"/></div><p class="paragraph" style="text-align:left;">So here, we have used the <code>set</code> statement to specify properties of the <code>document</code>, <code>text</code> and <code>page</code> objects. There, we’ve set some of the objects attributes (like <code>title</code>, <code>font</code> or <code>paper</code>) to values that were</p><ul><li><p class="paragraph" style="text-align:left;">either hard-coded (like <code>&quot;Source Sans Pro&quot;</code> or the margins) or</p></li><li><p class="paragraph" style="text-align:left;">filled using arguments of the <code>#let()</code> function (like <code>author</code> or <code>paper</code>).</p></li></ul><hr class="content_break"><h1 class="heading" style="text-align:left;" id="add-a-page"><b>Add a page</b></h1><p class="paragraph" style="text-align:left;">So far so good. We’ve set a couple of things. But we haven’t added any content to the layout yet. Let’s change that.</p><p class="paragraph" style="text-align:left;">Let’s insert a page using the <code>page()</code> function. In there, we can make sure that everything is left-aligned and starts at the top of the page using <code>align()</code>. The syntax for that is</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/34a2ad1d-adee-42ef-bef6-2ef60b6993de/image.png?t=1743423567"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="add-content"><b>Add content</b></h1><p class="paragraph" style="text-align:left;">See that line that says “page content goes” here? That’s where we can place the content of the page. Here, let’s just try to use the <code>body</code> variable from the <code>article()</code> function to insert everything that is inside our Quarto document.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/832592e1-4558-4e08-90ad-fbb16e8baf7f/image.png?t=1743423585"/></div><p class="paragraph" style="text-align:left;">That should be a valid layout. Let’s try to render this. Here’s what we’ll get:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c64bd559-aa7b-4799-b526-2ae15589dc24/ksnip_20250331-131721.png?t=1743423884"/></div><p class="paragraph" style="text-align:left;">Oh no. That’s a bit dumb. Instead of understanding <code>body</code> as variable, Typst things that we actually want to use a literal text. But we have used other variables just like that before, haven’t we? What’s going on?</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="markdown-vs-evaluation-context"><b>Markdown vs evaluation context</b></h1><p class="paragraph" style="text-align:left;">You see, we are currently filling the <code>align()</code> function inside the <code>page()</code> function with content. This content is inside brackets <code>[]</code> where it is evaluated as Markdown. Not in any functional kind of way. And the magical signal for Typst to switch to an evaluated context is <code>#</code>.</p><p class="paragraph" style="text-align:left;">That’s also why the <code>let()</code> function to define the article layout started with <code>#</code>. Otherwise, Typst would think that our file is just filled with plain text and won’t evaluate anything. And the same has do be done now that we are inside a Markdown content block inside the brackets of <code>align()</code>. So, let’s try this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6ca9b5b2-7b2f-4368-8e11-3c3d61d4a08c/image.png?t=1743423620"/></div><p class="paragraph" style="text-align:left;">Ahh much better. There’s all of our content. And notice how everything fits on one page now.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e24e7ba0-4459-4bb8-af4c-a325e94f25cb/ksnip_20250331-131722.png?t=1743423894"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="add-our-parameters"><b>Add our parameters</b></h1><p class="paragraph" style="text-align:left;">Similarly, we can add our parameters using the <code>text()</code> function. The syntax is the same as with <code>align()</code>:</p><ul><li><p class="paragraph" style="text-align:left;">First, we fill <code>text()</code> with arguments like <code>text(size:1.6em)</code>.</p></li><li><p class="paragraph" style="text-align:left;">Then, we create actual content inside the <code>brackets</code> like `text(size: 1.6em)[content].</p></li><li><p class="paragraph" style="text-align:left;">And finally we have to use <code>#</code> inside the Markdown content blocks to use functions and variables.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/1d3dfabb-7b4f-48c3-9e7a-80b57ec41fca/image.png?t=1743423635"/></div><p class="paragraph" style="text-align:left;">This will give us this terrible look.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/0d545e15-ba20-4635-8221-657923031af2/image.png?t=1743423942"/></div><p class="paragraph" style="text-align:left;">Let’s add some vertical space with the <code>v()</code> function.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/24973ee3-d95d-4fa5-b16f-abfab43e2fc7/image.png?t=1743447147"/></div><p class="paragraph" style="text-align:left;">And then we have way more space:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/97e940fb-d637-4db4-9b23-5cf695b96e6c/image.png?t=1743423970"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">Ahh much better. Let that sink in for now. Next week, I’m showing you how to add colors to our designs.</p><p class="paragraph" style="text-align:left;">And as always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-creating-beautiful-pdf-reports-with-typst-and-quarto" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=1ebcc84d-0309-46c4-b83f-c638a9eccdaf&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Scalable Reporting with Quarto)</title>
  <description>I show you how generate lots of PDFs via Quarto by using parameterized reports that iterate through lots and lots of placeholders and modify the PDF accordingly</description>
  <link>https://3mw.albert-rapp.de/p/scalable-reporting-with-quarto</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/scalable-reporting-with-quarto</guid>
  <pubDate>Wed, 23 Apr 2025 18:46:00 +0000</pubDate>
  <atom:published>2025-04-23T18:46:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. <b>Parameterized reports</b> are a powerful but often underutilized strategy for communicating data to multiple stakeholders.</p><p class="paragraph" style="text-align:left;">Let’s say you have several departments in your organization. A common instinct is to build a dashboard where users can click around to see the data for their department.</p><p class="paragraph" style="text-align:left;">But what if, instead, you could <b>automatically generate one customized report per department</b> and send those out directly? In today’s newsletter, I’ll show you how to do just that using <b>Quarto</b>.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="create-a-basic-report-template"><b>Create a Basic Report Template</b></h1><p class="paragraph" style="text-align:left;">First, we need a sample report. We’ll use the <code>palmerpenguins</code> dataset to simulate a situation where each penguin species represents a department.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/1cf473b9-12d4-4257-848e-1fbf3a01ec8e/image.png?t=1743423074"/></div><p class="paragraph" style="text-align:left;"></p><p class="paragraph" style="text-align:left;">This will give us a PDF output like this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/527e4926-fbaf-4ae4-b81b-a5dfe9830ced/image.png?t=1743446666"/></div><hr class="content_break"><h2 class="heading" style="text-align:left;" id="add-parameters-to-the-yaml-header"><b>Add Parameters to the YAML Header</b></h2><p class="paragraph" style="text-align:left;">Here, we’ve used the <code>&quot;Adelie&quot;</code> species to act a placeholder. Next, we have to make sure that we can easily replace the species in all instances of the text and code. To do that, we define a <code>params</code> section in the YAML header:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b657efe9-d884-40bc-b8e4-99e70f54a0ee/image.png?t=1743423105"/></div><p class="paragraph" style="text-align:left;"><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">Now, wherever we want to reference </span><code>species</code><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;"> in the document, we use </span><code>params$species</code><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">. This allows the content of the report to adapt to whatever value we plug into the parameter. It works in code chunks:</span></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/041e7173-f27f-4467-88e6-e0acba3f7c63/image.png?t=1743423117"/></div><p class="paragraph" style="text-align:left;"><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">And it works in inline text as well:</span></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/06b3ef71-f14d-4faf-8b6c-7bc9bb35d36b/image.png?t=1743423127"/></div><p class="paragraph" style="text-align:left;">Now we can try to change <code>&quot;Adelie&quot;</code> to <code>&quot;Gentoo&quot;</code> and re-render the report. You’ll see the whole report adjusts accordingly (most notably seen by the plot change.)</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e298df22-f84a-4768-8372-78afc5f78bb8/image.png?t=1743446578"/></div><hr class="content_break"><h2 class="heading" style="text-align:left;" id="automate-rendering-for-multiple-par"><b>Automate Rendering for Multiple Parameters</b></h2><p class="paragraph" style="text-align:left;">Now the real power kicks in. We want to render <b>one report per species</b>, or in your real-world scenario, <b>one report per department</b>. To do that, we have to create a separate R script that uses the <code>quarto_render()</code> function from the <code>&#123;quarto&#125;</code> package:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/dec7d556-27f0-481e-8ccd-3e896bb26ef9/image.png?t=1743423149"/></div><p class="paragraph" style="text-align:left;">This script loops over all species and renders a separate PDF report for each one.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/02892e85-dff7-44b7-9176-72bf45229a10/ksnip_20250331-131720.png?t=1743423182"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">With just a few lines of configuration and code, you now have a scalable way to generate <b>customized PDF reports for any number of stakeholders or categories</b>. Whether you’re reporting by department, product line, region, or team, <b>parameterized Quarto documents</b> make it simple and powerful. </p><p class="paragraph" style="text-align:left;">Next week, we’re going to make that report prettier using the Typst-PDF format. And as always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-scalable-reporting-with-quarto" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=27e79a2a-9c5d-4151-8aa3-ce13f5148055&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Brand.yml: One Theme to Style Them All ✨)</title>
  <description>How to use the brand.yml styling mechanism. It works for Quarto documents as well as R-Shiny &amp; Py-Shiny apps. Fantastic for keeping a consistent style.</description>
  <link>https://3mw.albert-rapp.de/p/brand-yml-one-theme-to-style-them-all</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/brand-yml-one-theme-to-style-them-all</guid>
  <pubDate>Wed, 16 Apr 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-04-16T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. Have you heard about <code>brand.yml</code>? It’s one of Posit’s newest and most exciting additions to their product lineup. With <code>brand.yml</code>, you can define a <b>unified theme</b> that works seamlessly across</p><ul><li><p class="paragraph" style="text-align:left;">Quarto documents,</p></li><li><p class="paragraph" style="text-align:left;">Shiny for R apps, and</p></li><li><p class="paragraph" style="text-align:left;">Shiny for Python apps.</p></li></ul><p class="paragraph" style="text-align:left;">In today’s newsletter, I’ll walk you through what <code>brand.yml</code> is and how to use it to bring consistent styling to all your projects.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="whats-the-idea"><b>What’s the idea?</b></h1><p class="paragraph" style="text-align:left;">The idea behind <code>brand.yml</code> is simple but powerful:</p><ol start="1"><li><p class="paragraph" style="text-align:left;">You define your <b>primary color</b>, <b>secondary color</b>, <b>fonts</b>, <b>logo</b>, and other branding settings in a single <code>brand.yml</code> file.</p></li><li><p class="paragraph" style="text-align:left;">You can then reuse that same configuration across all your data products. No need to redefine styles in each individual project.</p></li></ol><p class="paragraph" style="text-align:left;">This makes it easier to</p><ul><li><p class="paragraph" style="text-align:left;">maintain consistent branding,</p></li><li><p class="paragraph" style="text-align:left;">reuse themes across projects, and</p></li><li><p class="paragraph" style="text-align:left;">share themes across teams.</p></li></ul><hr class="content_break"><h1 class="heading" style="text-align:left;" id="how-does-this-work"><b>How does this work?</b></h1><p class="paragraph" style="text-align:left;">You’re probably now wondering: What does a <code>brand.yml</code> file actually look like? Well, let me show you. It’s just a plain text YAML file. Here’s an example from <a class="link" href="https://posit-dev.github.io/brand-yml/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank" rel="noopener noreferrer nofollow">the official docs</a>:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/709079cb-52bb-4d90-a641-f07a3c4d31e1/image.png?t=1743422732"/></div><p class="paragraph" style="text-align:left;">As you can see, it looks pretty simple. But this simple file becomes the central definition of your app or document’s look and feel.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="how-to-use-brandyml"><b>How to Use </b><code>brand.yml</code><b>?</b></h1><p class="paragraph" style="text-align:left;">The way you use this file depends on your toolchain. Here’s a breakdown for each use case:</p><h3 class="heading" style="text-align:left;" id="in-quarto">📄<b> In Quarto</b></h3><p class="paragraph" style="text-align:left;">First, you need to save the branding content into a file called <code>_brand.yml</code>. And to apply the brand in a Quarto document you just have to add the <code>brand</code> attribute to the YAML header and fill it with the path to your yml-file. This could look something like this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/194cee5f-00fb-4fa9-b42e-4bbf0c58ead9/image.png?t=1743422777"/></div><p class="paragraph" style="text-align:left;">It doesn’t get any easier than that. And if you want to use the specified branding options (e.g. colors) in a particular setting (like Typst PDFs), then you can check out the dedicated <span style="text-decoration:underline;"><a class="link" href="https://quarto.org/docs/authoring/brand.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all#overview" target="_blank" rel="noopener noreferrer nofollow" style="color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1))">Quarto documentation</a></span> on that.</p><hr class="content_break"><h3 class="heading" style="text-align:left;" id="in-shiny-for-r"><b>💻 In Shiny for R</b></h3><p class="paragraph" style="text-align:left;">In Shiny for R, <code>brand.yml</code> is integrated via the fantastic <code>&#123;bslib&#125;</code> package.<br>You can use it in your UI definition like so:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9cb6f7cc-76f0-4570-a5bc-4676dd020f01/image.png?t=1743422799"/></div><hr class="content_break"><h3 class="heading" style="text-align:left;" id="in-shiny-for-python">🐍<b> In Shiny for Python</b></h3><p class="paragraph" style="text-align:left;">You’ll need the latest version of <b>Py-Shiny</b> installed with the <code>theme</code> extra.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/77aeabcc-ff5a-4019-9645-2cabeff24e82/image.png?t=1743422813"/></div><p class="paragraph" style="text-align:left;"><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">Once you’ve got that, you can use </span><code>brand.yml</code><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;"> like this:</span></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/801a9151-28cd-4548-8bf5-2bb2c9e9b15e/image.png?t=1743422820"/></div><p class="paragraph" style="text-align:left;"><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">And if you’re using </span><b>Py-Shiny Express</b><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">, the usage is slightly different. There, you’ll have to configure the </span><code>page_options</code><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;"> argument in the UI object.</span></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/55cae1e3-e57c-46e6-a12e-d1779586b714/image.png?t=1743422864"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">I think <code>brand.yml</code> is a fantastic idea. It simplifies theming, supports consistency, and works beautifully across multiple frameworks. If you’re building out a data product pipeline that includes reports and interactive apps, this tool will save you time and help keep everything looking polished and on-brand.</p><p class="paragraph" style="text-align:left;">Let me know what you think about <code>brand.yml</code>. And as always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-brand-yml-one-theme-to-style-them-all" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=887f3bae-bbf0-40a1-8684-3b24badff938&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Using the new Positron IDE)</title>
  <description>I show you how I&#39;ve set up the new Positron IDE for data science workflows with R and Python. Additionally, I share settings that work for me.</description>
  <link>https://3mw.albert-rapp.de/p/using-the-new-positron-ide</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/using-the-new-positron-ide</guid>
  <pubDate>Wed, 09 Apr 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-04-09T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. Recently, I’ve been playing around with the new <b>Positron</b> IDE, and I must say: I really enjoy it. It still has some small bugs but overall it’s great. More importantly, it’s packed with features tailored for data science workflows.</p><p class="paragraph" style="text-align:left;">In this week’s newsletter, I want to share my favorite features, settings, and shortcuts in Positron. That way, you can get a sense of why it might be a better fit than VSCode for your R or Python work.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="fixed-console-for-r-and-python"><b>Fixed Console for R and Python</b></h1><p class="paragraph" style="text-align:left;">One of the standout features in Positron is the <b>fixed console</b> for R and Python that never goes away. Unlike VSCode, there’s always a R or Python console that you can use for quick iterations. Also, you can easily switch between languages and even between different versions of R and Python. </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3a1dcc1b-489b-4a9a-8adb-6436fe38c1f6/image.png?t=1743422041"/></div><p class="paragraph" style="text-align:left;">And regardless of what you use, there’s a dedicated console that always receives your commands when you press <b>Ctrl + Enter</b> in the editor. This makes it far more reliable than what I experienced with VS Code, where the console sometimes wouldn’t respond or would detach from the current session. </p><p class="paragraph" style="text-align:left;">And to make it perfectly clear, just for this feature alone, I’d already recommend Positron over VS Code.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="integrated-help-pane-f-1-to-view-fu"><b>Integrated Help Pane (F1 to View Function Docs)</b></h1><p class="paragraph" style="text-align:left;">Just like in RStudio, Positron lets you press <b>F1</b> on any function in your script to open the Help page.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c7e39601-ce95-44ec-b78d-276cfa9bf5d0/image.png?t=1743422180"/></div><p class="paragraph" style="text-align:left;">No more switching to a browser or dealing with limited pop-ups like in VS Code. This feature is built-in and persistent. It’s especially handy when you have to refer to arguments or function references on the fly.</p><p class="paragraph" style="text-align:left;">The only issue that I have is that the formatting in the help windows isn’t always great. In particular, if you increase your editor font size. In that case, you will have a large code font and regular text font inside the help panel.</p><p class="paragraph" style="text-align:left;">That’s not particularly great but I hope the kind people behind Positron <a class="link" href="https://github.com/posit-dev/positron/issues/7039?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide#issuecomment-2761614670" target="_blank" rel="noopener noreferrer nofollow">are already on it</a>. For now a workaround is to increase the window size instead if you want to have larger fonts.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="sideby-side-layout-just-like-r-stud"><b>Side-by-Side Layout (Just Like RStudio)</b></h1><p class="paragraph" style="text-align:left;">I love Positron’s layout customization. When you download the newest version, there’s a button in the top-right corner to switch layouts. </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/53cc2de0-d808-4283-918a-1a17a21de95f/image.png?t=1743422262"/></div><p class="paragraph" style="text-align:left;">I always go with the <b>side-by-side layout</b>, similar to what I used in RStudio:</p><ul><li><p class="paragraph" style="text-align:left;">Left: Script or Quarto file </p></li><li><p class="paragraph" style="text-align:left;">Right: Console, plots, and environment</p></li></ul><p class="paragraph" style="text-align:left;">This makes transitioning from my previous RStudio setup feel completely natural.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="zen-mode-for-maximum-focus"><b>Zen Mode for Maximum Focus</b></h1><p class="paragraph" style="text-align:left;">Positron has a fantastic <b>Zen mode</b> that lets you minimize distractions and maximize space. That way, only the essential UI things are maximized. Here’s how it looks as I’m writing this newsletter.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a9d500ed-9bd9-4931-9b52-ea31f6679734/ksnip_20250331-131716.png?t=1743422325"/></div><p class="paragraph" style="text-align:left;">Depending on what I need at the moment, I can toggle between:</p><ul><li><p class="paragraph" style="text-align:left;">Code only</p></li><li><p class="paragraph" style="text-align:left;">Code + Console</p></li><li><p class="paragraph" style="text-align:left;">Code + Console + File Explorer</p></li></ul><hr class="content_break"><h1 class="heading" style="text-align:left;" id="familiar-shortcuts-from-r-studio"><b>Familiar Shortcuts from RStudio</b></h1><p class="paragraph" style="text-align:left;">Positron supports many of your favorite RStudio shortcuts:</p><ul><li><p class="paragraph" style="text-align:left;"><b>Ctrl + Shift + M</b> → Insert pipe (<code>|&gt;</code>)</p></li><li><p class="paragraph" style="text-align:left;"><b>Ctrl + Shift + K</b> → Render Quarto document</p></li></ul><p class="paragraph" style="text-align:left;">I’ve also customized a few additional shortcuts to toggle the sidebars for Zen mode (like I’ve just described). Or to jump between console and editor.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/99a84fc6-af5d-4023-968f-73cf6f9c550a/image.png?t=1743421850"/></div><p class="paragraph" style="text-align:left;">And in case this feels intimidating, there’s also a UI that you can use to tweak these things. It’s just easier to share the settings with you this way.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="use-the-command-palette-ctrl-shift-"><b>Use the Command Palette (Ctrl + Shift + P)</b></h1><p class="paragraph" style="text-align:left;">The <b>Command Palette</b> is your best friend in Positron. Press <b>Ctrl + Shift + P</b> to access any command or setting.</p><p class="paragraph" style="text-align:left;">Want to enter Zen Mode? Type “Zen” and the relevant action will pop up. You’ll also see the keyboard shortcut for it, helping you memorize it over time</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a4f2575b-3365-4b17-bbe8-5af939e1a5d9/image.png?t=1743422405"/></div><p class="paragraph" style="text-align:left;"><b>Pro tip: </b>If you delete the arrow <code>&gt;</code> that shows up in the palette, it becomes a fuzzy finder for files and objects in your workspace.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/73a3a653-f88a-4251-a0d0-93ff54131cdb/image.png?t=1743422435"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="projects-nope-directories-instead"><b>Projects? Nope. Directories Instead.</b></h1><p class="paragraph" style="text-align:left;">Positron doesn’t use “projects” the way RStudio does. Instead, it uses <b>directories</b>. If you had an RStudio project before, just open the directory in Positron using: <code>Ctrl + K</code> followed by <code>Ctrl + O</code> </p><p class="paragraph" style="text-align:left;">That directory becomes your workspace root. And everything inside it is visible in the file explorer. Pretty much like RStudio projects.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="customize-everything-with-settingsj"><b>Customize Everything with </b><code>settings.json</code></h1><p class="paragraph" style="text-align:left;">Like VSCode, Positron is fully customizable via the <code>settings.json</code> file. Open it via the Command Palette and throw in any setting you want. Here are some of my favorites:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/781a2895-d986-42ee-83ac-d25ab472ce7e/image.png?t=1743421827"/></div><p class="paragraph" style="text-align:left;">And just like with the <code>keybindings.json</code>, there’s also a UI that you can use.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Positron is a joy to use. It brings the best of VSCode’s extensibility and combines it with RStudio’s comfort, especially for data scientists. Let me know if you’re using it already and what your favorite tweaks are. I’d love to hear what’s working for you!</p><p class="paragraph" style="text-align:left;">As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-the-new-positron-ide" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=8cf44829-75e4-4bac-b0c2-abd3eac1f375&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Automatic Time Series Collection With {pins} &amp; GH Actions)</title>
  <description>I show you how to use GitHub Actions and the {pins} R package to easily collect time series and store that in an AWS S3 bucket.</description>
  <link>https://3mw.albert-rapp.de/p/automatic-time-series-collection-with-pins-gh-actions</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/automatic-time-series-collection-with-pins-gh-actions</guid>
  <pubDate>Wed, 02 Apr 2025 17:00:00 +0000</pubDate>
  <atom:published>2025-04-02T17:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 10.0px 10.0px 10.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. In today’s newsletter, I want to show you how you can combine the <code>&#123;pins&#125;</code> package with GitHub Actions. That way, you can automate the process of downloading data from the internet and saving it as a time series. </p><p class="paragraph" style="text-align:left;">The workflow is pretty similar to one of our previous newsletter on GitHub Actions. So if you’ve read <a class="link" href="https://3mw.albert-rapp.de/p/automate-anything-with-r-github-actions?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">that newsletter</a>, then you should have no problem following along.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="a-repo-for-our-project"><b>A repo for our project</b></h1><p class="paragraph" style="text-align:left;">The first thing we need is a new project for our data extraction endeavor. But let’s not start completely from scratch. Let’s use our <a class="link" href="https://github.com/AlbertRapp/gh_actions_test/blob/2b7e278ff43b684a6d13a290b8692f0da16701a7/.github/workflows/main.yml?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">“gh_actions_test” repo</a>. It already has an <code>&#123;renv&#125;</code> environment for version control set up. That way, we don’t have to worry about that.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a9956ccb-81b9-4d23-8a86-64007135cbce/image.png?t=1743421435"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="add-pins-to-renv"><b>Add pins to </b><code>&#123;renv&#125;</code></h1><p class="paragraph" style="text-align:left;">Now we can add <code>&#123;pins&#125;</code> to our <code>&#123;renv&#125;</code> environment. Simply call the <code>install()</code> command.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/515b03e4-f9de-49f7-a43d-ed48a130ff65/image.png?t=1743421474"/></div><p class="paragraph" style="text-align:left;">Then, we can create a new R-Script <code>pins-demo.R</code> in which we’ll actually use <code>&#123;pins&#125;</code>. For now, this should only contain this code:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/24d4f4b6-6ba5-4185-bb2f-335a1fbf7e38/image.png?t=1743421487"/></div><p class="paragraph" style="text-align:left;">That way, <code>&#123;renv&#125;</code> lets us write the <code>&#123;pins&#125;</code> package to its lock file. If you recall, this is the thing we have to restore at the beginning of every GH workflow. Now make sure that</p><ul><li><p class="paragraph" style="text-align:left;">you can execute this code in your project, i.e. you have AWS credentials set,</p></li><li><p class="paragraph" style="text-align:left;">that you have your <code>.Rprofile</code> file removed from the git repo and added it to <code>.gitignore</code> (because you don’t want to share your keys),</p></li><li><p class="paragraph" style="text-align:left;">and that you saved the packages to the lock file via <code>renv::snapshot()</code>.</p></li></ul><p class="paragraph" style="text-align:left;">Alright, cool. So with that we need a new GH actions workflow file.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="base-git-hub-actions-workflow"><b>Base GitHub Actions Workflow</b></h1><p class="paragraph" style="text-align:left;">Let’s start out with <code>.yml</code> workflow file from our last GitHub Actions tutorial. That’s a good place to start I’d say.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f24ea933-cca5-4f74-8551-4c6551bb6976/image.png?t=1743421301"/></div><p class="paragraph" style="text-align:left;">In this project, we don’t need anything from Quarto and we also don’t need to commit to Github, so we can remove those steps.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b53a4993-adc4-4603-aa31-db0616da866c/image.png?t=1743421347"/></div><p class="paragraph" style="text-align:left;">Unfortunately, R isn’t contained in the <code>ubuntu-latest</code> machine from GitHub anymore. That’s why we have to add R ourselves. But that’s super easy to do. We only have to use one of the R containers provided from the<a class="link" href="https://rocker-project.org/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow"> Rocker Project</a>.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/af6f9810-5ccf-4f74-bd4f-fbdde48e8224/image.png?t=1743421506"/></div><p class="paragraph" style="text-align:left;">And with that we are once again ready to use R automations.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="extract-data"><b>Extract Data</b></h1><p class="paragraph" style="text-align:left;">Next, we need an R function that fetches data from an external source. This could be via</p><ul><li><p class="paragraph" style="text-align:left;">API calls,</p></li><li><p class="paragraph" style="text-align:left;">web scrapings, or</p></li><li><p class="paragraph" style="text-align:left;">any other data retrieval method.</p></li></ul><p class="paragraph" style="text-align:left;">To keep things simple, we’ll simulate it with a function that just returns a random value:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a910a5f8-65a2-4376-81dd-a13f8b505eec/image.png?t=1743421516"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="check-if-pin-is-available"><b>Check if pin is available</b></h1><p class="paragraph" style="text-align:left;">In the next step, we want to write this data to a pin that is stored in our board in S3. For that, we first need to check if our pin is even available. If not, we simply write to that pin without doing anything else.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c8dfa588-7377-4fba-b179-9c122904b4f2/image.png?t=1743421528"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="grab-previous-data"><b>Grab previous data</b></h1><p class="paragraph" style="text-align:left;">If the pin is already available, then we should</p><ul><li><p class="paragraph" style="text-align:left;">grab the already saved data,</p></li><li><p class="paragraph" style="text-align:left;">append our new data to it, and</p></li><li><p class="paragraph" style="text-align:left;">write that new complete data to the same pin.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/70fd150e-ce3f-4df0-bdeb-ce4fcee6e3db/image.png?t=1743421544"/></div><p class="paragraph" style="text-align:left;">And that’s it. <code>&#123;pins&#125;</code> will do all the data versioning for us. So overall, our <code>pins-demo.R</code> script is only a short little file like this:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7536683e-acb7-4f43-bb35-4d547ec82b2f/image.png?t=1743421556"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="modify-gh-workflow"><b>Modify GH workflow</b></h1><p class="paragraph" style="text-align:left;">Sweet. Now, we only have to tell our GH Actions workflow to run that script. The easiest way is to add another step after all dependencies are installed.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/d51c06e2-dae5-4d80-88cc-88c999c4b720/image.png?t=1743421586"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="add-aws-credentials-to-git-hub-secr"><b>Add AWS Credentials to GitHub Secrets</b></h1><p class="paragraph" style="text-align:left;">But if you think about it, this cannot work yet. The machine that is supposed to execute this code, doesn’t know our GitHub credentials. If this script works on the GH action, then you should seriously check if you’ve accidentally pushed your <code>.Rprofile</code> file (which you should absolutely not do.)</p><p class="paragraph" style="text-align:left;">So that’s why we have to tell our step about the environment variables it needs.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/bf5a672e-5112-44ab-a4c4-1d8fc67de878/image.png?t=1743421601"/></div><p class="paragraph" style="text-align:left;">And then in your GitHub repository, go to <b>Settings &gt; Secrets and variables &gt; Actions</b>, and add:</p><ul><li><p class="paragraph" style="text-align:left;"><code>AWS_ACCESS_KEY_ID</code></p></li><li><p class="paragraph" style="text-align:left;"><code>AWS_SECRET_ACCESS_KEY</code></p></li><li><p class="paragraph" style="text-align:left;"><code>AWS_DEFAULT_REGION</code></p></li></ul><hr class="content_break"><p class="paragraph" style="text-align:left;">And that’s it! Now every time the flow runs, we will have added a new row to our dataset.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5954e6a6-22a4-478c-b9e0-6c01951cdc80/image.png?t=1743421623"/></div><p class="paragraph" style="text-align:left;">You now have a working automation that pulls data from anywhere you like and stores it in cloud storage securely and automatically.</p><p class="paragraph" style="text-align:left;">As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-automatic-time-series-collection-with-pins-gh-actions" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=a61728ea-5a53-497f-b403-4e626d58ff45&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Storing {pins} on GitHub and AWS S3)</title>
  <description>Pins are a fantastic tool to keep track of data versions. Here, I show you how to leverage online storages like GitHub repos or AWS S3 to save these pins.</description>
  <link>https://3mw.albert-rapp.de/p/storing-pins-on-github-and-aws-s3</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/storing-pins-on-github-and-aws-s3</guid>
  <pubDate>Wed, 26 Mar 2025 18:00:00 +0000</pubDate>
  <atom:published>2025-03-26T18:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Source Sans 3','Source Sans Pro',Roboto,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'700' !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 15.0px 0.0px 15.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. In this week’s newsletter, I’ll show you how to use the <code>&#123;pins&#125;</code> package to store your data on different online platforms. Basically, this is a follow-up to <a class="link" href="https://3mw.albert-rapp.de/p/using-pins-for-data-storage?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">last week’s newsletter</a>.</p><p class="paragraph" style="text-align:left;">And there are many places where you can store pins. Here, we’ll walk through two particuclar examples. Namely, GitHub and AWS S3. But before I show you how they work, let me show you my usual announcements.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="interactive-documents-full-app">Interactive Documents &gt; Full App</h1><p class="paragraph" style="text-align:left;">Ever found yourself building a Shiny app that contains mostly text with just a few interactive parts? That’s a bit of a nuisance to set up because you’re mostly trying to make your text look nice inside your app’s big blank canvas. </p><p class="paragraph" style="text-align:left;">Now here’s a better way.</p><p class="paragraph" style="text-align:left;">Just create a Quarto document! This will immediately use formatting that is proper for text-heavy documents. </p><p class="paragraph" style="text-align:left;">And the interactive part? </p><p class="paragraph" style="text-align:left;">Well, in Quarto you can add them via Shiny server code chunks. And in my newest YT video I show you how that works. Check it out:</p><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="true" class="youtube_embed" frameborder="0" height="100%" src="https://youtube.com/embed/06H8k1nzZQ0" width="100%"></iframe><hr class="content_break"><h1 class="heading" style="text-align:left;" id="using-git-hub-as-a-pin-board">Using GitHub as a Pin Board</h1><p class="paragraph" style="text-align:left;">Let’s assume you have a public GitHub repository with pins stored in it. You can connect to it using the <code>board_url()</code> function. Here’s an example of that using pins from the public <code>&#123;pins&#125;</code> repo.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/93d05027-06b0-40db-841e-4541ff5deec2/grafik.png?t=1742837553"/></div><p class="paragraph" style="text-align:left;">Once you’ve created the board, you can read pins from it using the <code>pin_read()</code> function:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6efe4a17-7756-4766-81bd-943efc7c6067/grafik.png?t=1742837570"/></div><p class="paragraph" style="text-align:left;">But this only works with pins that contain actual R data sets. For example the <code>raw</code> pin contains a <code>.txt</code> file. That’s why it can’t be opened in the R console.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7b2bb862-1774-406f-8966-863d8e971ed5/grafik.png?t=1742837589"/></div><p class="paragraph" style="text-align:left;">Instead, you have to download the file.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fd081082-7410-47af-be2a-412754eeb45d/grafik.png?t=1742837603"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="using-git-hub-with-private-repos">Using GitHub with Private Repos</h1><p class="paragraph" style="text-align:left;">What if you want to use a <b>private</b> repository instead?</p><p class="paragraph" style="text-align:left;">In that case, you’ll need to include your <b>GitHub Personal Access Token</b> in the request. You do this by first creating a named vector with your token as the authorization header.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c6cfb06e-547f-497b-ad24-7dd283a786cb/grafik.png?t=1742837619"/></div><p class="paragraph" style="text-align:left;">And then you could pass it to the <code>headers</code> argument of <code>board_url()</code>. Here, I’ve just taken the example from the <code>&#123;pins&#125;</code><a class="link" href="https://pins.rstudio.com/reference/board_url.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3#authentication-for-board-url-" target="_blank" rel="noopener noreferrer nofollow"> docs</a>.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/09872fb5-4775-4783-924b-e575e1e04ae6/grafik.png?t=1742837631"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="limitations-of-pins-with-git-hub">Limitations of Pins with GitHub</h1><p class="paragraph" style="text-align:left;">Note that using pins like that only allows reading from GitHub. It doesn’t let you modify the data. If you want to change pins from a GitHub repo, you’d have to:</p><ol start="1"><li><p class="paragraph" style="text-align:left;">Clone the repository</p></li><li><p class="paragraph" style="text-align:left;">Modify the pins locally</p></li><li><p class="paragraph" style="text-align:left;">Push the changes back to GitHub</p></li></ol><p class="paragraph" style="text-align:left;">This isn’t the most convenient workflow. That’s why I prefer other options like AWS S3.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="using-aws-s-3-as-a-pin-board">Using AWS S3 as a Pin Board</h1><p class="paragraph" style="text-align:left;">For a smoother experience, AWS S3 is a great option.<br>To use it, you need an existing <b>S3 bucket</b> to store your pins. If you don’t have one yet, check out the tutorial <a class="link" href="https://3mw.albert-rapp.de/p/save-data-at-aws-s3-with-paws?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">I wrote a few weeks back</a> on how to create an S3 bucket.</p><p class="paragraph" style="text-align:left;">Once you have your bucket and region ready, you can connect using the <code>board_s3()</code> function:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/94450fa6-76b3-416c-8864-746ea4628960/grafik.png?t=1742837654"/></div><p class="paragraph" style="text-align:left;">If you encounter an “Access Denied” error, it’s likely because your <b>AWS credentials</b> are not set up correctly. You need to have the following environment variables configured:</p><ul><li><p class="paragraph" style="text-align:left;"><code>AWS_ACCESS_KEY_ID</code></p></li><li><p class="paragraph" style="text-align:left;"><code>AWS_SECRET_ACCESS_KEY</code></p></li></ul><p class="paragraph" style="text-align:left;">You can set these in your <code>.Renviron</code> file or in your R session.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="writing-pins-to-aws-s-3">Writing Pins to AWS S3</h1><p class="paragraph" style="text-align:left;">Once your S3 board is set up and authenticated, you can read and write pins just like with a local board.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/43e59f89-f915-46c8-a2d7-2292f6753822/grafik.png?t=1742837671"/></div><p class="paragraph" style="text-align:left;">The key benefit here is that you don’t need to manually download or push data. <code>&#123;pins&#125;</code> handles it all automatically. In fact, if you take a look at your S3 bucket now, you’ll see that the data is already there.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e7c024b6-7b83-4382-9bf0-e6c28c03a9a4/grafik.png?t=1742837758"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">With that, you have two solid ways to store your pins online. Next week, I’ll show you how to set up an automation on GitHub Actions that automatically collects time series data and stores it using the <code>&#123;pins&#125;</code> package.</p><p class="paragraph" style="text-align:left;">As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p><p class="embed__link"> data-cleaning.albert-rapp.de </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p><p class="embed__link"> arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p><p class="embed__link"> rfortherestofus.com/courses/tables </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-storing-pins-on-github-and-aws-s3" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=cc496388-f119-4b1c-a189-3d90a42ebc28&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>3MW (Using {pins} for data storage)</title>
  <description>The {pins} package is a fantastic tool that makes data versioning super simple. In this post, I show you how its versioning mechanism works.</description>
  <link>https://3mw.albert-rapp.de/p/using-pins-for-data-storage</link>
  <guid isPermaLink="true">https://3mw.albert-rapp.de/p/using-pins-for-data-storage</guid>
  <pubDate>Wed, 19 Mar 2025 18:00:00 +0000</pubDate>
  <atom:published>2025-03-19T18:00:00Z</atom:published>
    <dc:creator>Albert Rapp</dc:creator>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#F1F1F1; }
  .bh__table_header p { color: #2A2A2A; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#e7f4fe;border-radius:10px;margin:0.0px 15.0px 0.0px 15.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:center;"><span style="color:#06436E;"><b>Enjoy 3 Minute Wednesdays at no cost.</b></span></p><p class="paragraph" style="text-align:left;">This newsletter is brought to you for free. If you want to <b>advance your R skills and support my work</b> at the same time, then you will like my paid offerings:</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank" rel="noopener noreferrer nofollow">Data Cleaning Master Class</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank" rel="noopener noreferrer nofollow">Insightful DataViz for “Uncreative” R Users</a></p></li></ul></div><p class="paragraph" style="text-align:left;">Guten Tag!</p><p class="paragraph" style="text-align:left;">Many greetings from Munich, Germany. In today’s newsletter, we are talking about the <code>&#123;pins&#125;</code> package. This package is not very well known in the R sphere, but it is a fantastic tool for keeping track of different data versions.</p><p class="paragraph" style="text-align:left;">Basically, <code>&#123;pins&#125;</code> makes storing data and versioning dead-simple. You can think of it as Git for your data. But before we dive in, I have a short thing to ask you: ‘</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="whats-next">What‘s next?</h1><p class="paragraph" style="text-align:left;">Recently, I find myself covering more and more technical aspects of data science that are not necessarily R focused. This includes:</p><ul><li><p class="paragraph" style="text-align:left;">Building automations with GitHub Actions</p></li><li><p class="paragraph" style="text-align:left;">Setting up infrastructure on AWS or Azure</p></li><li><p class="paragraph" style="text-align:left;">Using JavaScript to handle AI responses in Shiny apps</p></li></ul><p class="paragraph" style="text-align:left;">I do this because I think data science doesn’t happen in any single tool or language. Thus, I want to continue writing in as broad a scope as I feel like at the moment (after all I get to do whatever I want on this newsletter 🤪) </p><p class="paragraph" style="text-align:left;">But I do want to see if I can make this as valuable for you as possible. So let me know what you’re interested in by filling out this small poll. </p><p class="paragraph" style="text-align:left;">Just click on your favorite choice and it will be recorded. After that, you’ll also have the chance to leave additional comments in case you want to suggest something I haven’t thought of.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="why-use-the-pins-package"><b>Why use the </b><code>&#123;pins&#125;</code><b> package?</b></h1><p class="paragraph" style="text-align:left;">Now, before I show you how <code>&#123;pins&#125;</code> works, let’s talk about why you should even use it</p><ul><li><p class="paragraph" style="text-align:left;"><b>Version control</b>: Prevents accidental overwriting of important datasets when re-running workflows.</p></li><li><p class="paragraph" style="text-align:left;"><b>Efficient workflows</b>: You can run a calculation or an API call once and store the data permanently in a <b>pin</b>.</p></li><li><p class="paragraph" style="text-align:left;"><b>Metadata storage</b>: <code>&#123;pins&#125;</code> keeps detailed information about your data so you can easily restore or revert to previous versions.</p></li><li><p class="paragraph" style="text-align:left;"><b>Seamless integration</b> : You can store data anywhere you like. GitHub, Google Drive, AWS S3, you name it. <code>&#123;pins&#125;</code> will work exactly the same.</p></li></ul><p class="paragraph" style="text-align:left;"><a class="link" href="https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExaGpzYnRxajVxaWg4eTF0MHVjY3ZmaGd5Njl6MXpzeTIzZWZieG9ueCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/3oEjHLzm4BCF8zfPy0/giphy.gif?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank" rel="noopener noreferrer nofollow">Surely</a>, you’re wondering how all of that is supposed to work. So let’s dive into the technical details.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="set-up-pins"><b>Set up </b><code>&#123;pins&#125;</code></h1><p class="paragraph" style="text-align:left;">First, you need to install the package. As always, you can do this with:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/d80cb277-f995-4a8d-b72a-04360bb2e5c7/image.png?t=1742403244"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="set-up-a-board"><b>Set up a board</b></h1><p class="paragraph" style="text-align:left;">To store data, you need to place <b>“pins”</b> in a <b>“board”</b>. If you want to try <code>&#123;pins&#125;</code> locally first, create a board using:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a27db50c-f940-4148-9b5e-f63d4467ab20/image.png?t=1742403253"/></div><hr class="content_break"><h1 class="heading" style="text-align:left;" id="write-data-to-a-pin"><b>Write data to a pin</b></h1><p class="paragraph" style="text-align:left;">To write data to your board, simply use:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b7954fb9-e1b6-48eb-9788-8d3185dc95b5/image.png?t=1742403275"/></div><p class="paragraph" style="text-align:left;">This creates a new pin, and the best part is that previous data versions aren’t deleted.</p><hr class="content_break"><h1 class="heading" style="text-align:left;" id="retrieving-a-specific-version"><b>Retrieving a specific version</b></h1><p class="paragraph" style="text-align:left;">To check how many data versions exist in your board, use:</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4656ec2b-4d68-416a-96e0-a33a32369ec6/image.png?t=1742403294"/></div><p class="paragraph" style="text-align:left;"><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">That’s currently pretty boring. So let’s modify our data and overwrite our pin multiple times.</span></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a3a8eab5-28c9-412b-ab4f-379bdac218be/image.png?t=1742403308"/></div><p class="paragraph" style="text-align:left;"><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">Now, check out the different versions:</span></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7536471a-76ce-416a-90a8-ab57a406a170/image.png?t=1742403318"/></div><p class="paragraph" style="text-align:left;"><span style="color:rgb(33, 37, 41);font-family:system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;Noto Sans&quot;, &quot;Liberation Sans&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:17px;">Once you decide which version you want to load, retrieve it using:</span></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5b655f16-3d38-4143-bee3-b7bf8b4967b8/image.png?t=1742403331"/></div><hr class="content_break"><p class="paragraph" style="text-align:left;">As you can see, setting up <code>&#123;pins&#125;</code> is simple and efficient for storing and retrieving data. And the best thing is that you cannot accidentally overwrite data. Next week, I’ll show you how to set up cloud storages for your pins.</p><p class="paragraph" style="text-align:left;">As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me <a class="link" href="https://www.linkedin.com/in/dr-albert-rapp-9a5b9b28b/?utm_source=3mw.albert-rapp.de&utm_medium=referral&utm_campaign=3mw-look-at-all-those-quarto-outputs" target="_blank" rel="noopener noreferrer nofollow" style="color: rgb(6, 67, 110)">on LinkedIn</a> or <a class="link" href="https://bsky.app/profile/albertrapp.bsky.social?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank" rel="noopener noreferrer nofollow">on Bluesky</a>.</p><p class="paragraph" style="text-align:left;">See you next week, <br>Albert 👋</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Enjoyed this newsletter? Here are other ways I can help you:</p><div class="embed"><a class="embed__url" href="https://data-cleaning.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank"><div class="embed__content"><p class="embed__title"> Data Cleaning With R Master Class </p><p class="embed__description"> A data scientist’s guide to avoid wasting time with data cleaning. Learn 5 fundamental aspects of data cleaning, get to your insights much quicker. </p></div><img class="embed__image embed__image--right" src="https://data-cleaning.albert-rapp.de/assets/images/card.jpg?v=be98840b"/></a></div><div class="embed"><a class="embed__url" href="https://arapp.thinkific.com/courses/insightful-data-visualizations-for-uncreative-r-users?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank"><div class="embed__content"><p class="embed__title"> Insightful Data Visualizations for &quot;Uncreative&quot; R Users </p><p class="embed__description"> In this course, I teach you how to create insightful data visualizations without being a design expert. </p></div><img class="embed__image embed__image--right" src="https://import.cdn.thinkific.com/850523/SGJZ0Ry7TwOBHaC63yap_storytelling-ggplot(1).png"/></a></div><div class="embed"><a class="embed__url" href="https://rfortherestofus.com/courses/tables?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank"><div class="embed__content"><p class="embed__title"> Making Beautiful Tables with R </p><p class="embed__description"> Tables are often boring, hard to read, and, most importantly, they don&#39;t communicate effectively. In this course, I will show you that creating beautiful tables is just a matter of learning a few important principles. </p></div><img class="embed__image embed__image--right" src="https://rfortherestofus.com/img/containers/social_images/3.png/08ba5cd8dd720d5d42f823b1a456d87d.png"/></a></div><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.youtube.com/playlist?list=PLBnFxG6owe1EzWjq_rOfdWcWP8QBxcm58&utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank" rel="noopener noreferrer nofollow">My playlist on YouTube</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://yards.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank" rel="noopener noreferrer nofollow">Free book: Yet Again - R + Data Science</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://gt.albert-rapp.de/?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank" rel="noopener noreferrer nofollow">Free book: Beautiful tables with {gt}</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://albert-rapp.de/blog.html?utm_source=3mw.albert-rapp.de&utm_medium=newsletter&utm_campaign=3mw-using-pins-for-data-storage" target="_blank" rel="noopener noreferrer nofollow">Blog posts</a></p><p class="paragraph" style="text-align:left;"></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=a130d6f6-6360-4008-a699-bcb0791df4c5&utm_medium=post_rss&utm_source=3_minutes_wednesdays">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

  </channel>
</rss>
