R renv: How to Manage Dependencies in R Projects Easily
How many times has your code unexpectedly stopped working? Even better, how many times did the code work on your machine, but your coworkers couldn't run it? Both questions share the same underlying problem - <b>R environment</b>. That's where R <code>renv</code> comes in - a <a href="https://rstudio.github.io/renv/articles/renv.html" target="_blank" rel="nofollow noopener">dependency management package</a> that will ensure issues like these won't happen ever again. Today you'll learn all about <code>renv</code> through a hands-on example. You'll also see how to work with Plotly and Git. Let's get started! <blockquote>Need to make interactive Markdown documents? <a href="https://appsilon.com/r-quarto-tutorial/" target="_blank" rel="noopener">Try R Quarto - you'll never look back</a>.</blockquote> Table of contents: <ul><li><a href="#what-is-renv">What is R renv and Why Should You Care?</a></li><li><a href="#use-renv">2 Ways to Use renv in Your R Project</a></li><li><a href="#snapshots">How to Take Snapshots of your R Environment</a></li><li><a href="#restore">How to Restore your R Environment with a Single Command</a></li><li><a href="#summary">Summing up R renv</a></li></ul> <hr /> <h2 id="what-is-renv">What is R renv and Why Should You Care?</h2> Renv stands for <i>Reproducible Environment</i> and does just what the name suggests. Developers often have trouble managing the R environment and dependencies due to reasons of how R works by default. It installs packages to a central library and shares them between the projects. It sounds like a good and time-saving feature. After all, you don't need to install the same package in every project. But that's where the problems arise. You might have a newer version of some package than your coworkers - resulting in a deprecated or not-implemented functionality. End result? The app crashes or the code won't run altogether, and no one knows why because the code didn't change. The answer is always the same - environment differences and package version mismatch. R <code>renv</code> is here to create a separate, reproducible environment that you and your coworkers can use, hassle-free. To be more precise, <code>renv</code> will do the following: <ul><li>Create a project-specific library (no dealing with the central R library).</li><li>Create a list of dependencies and their version, making it easy to share the project.</li></ul> You now know why you should use <code>renv</code>, <b>but how do you actually go about it?</b> Let's answer this question next. <h2 id="use-renv">2 Ways to Use renv in Your R Project</h2> There are two distinct ways to leverage <code>renv</code> - when first creating a project and later through a command line. When creating a new project, just tick the second checkbox, as shown in the image below: <img class="size-full wp-image-15949" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f00a2fe7aed59a03484_1.webp" alt="Image 1 - Using renv when creating a new R project" width="1347" height="1008" /> Image 1 - Using renv when creating a new R project In case you forgot to do it, or prefer doing things through a command line, just type the following into the R console: <pre><code class="language-r">renv::activate()</code></pre> <img class="size-full wp-image-15951" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f00f69f7a868450b44e_2.webp" alt="Image 2 - Using renv through a command line" width="1347" height="1008" /> Image 2 - Using renv through a command line This will do all the housekeeping for you, and create several files and folders (we started with an empty directory): <img class="size-full wp-image-15953" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f01db018b429f997b91_3.webp" alt="Image 3 - Files and folders created by renv" width="927" height="548" /> Image 3 - Files and folders created by renv Let's discuss the purpose of each file next. <h3>Files and folders created by R renv - What do they mean?</h3> Here's the meaning behind every file/folder created by <code>renv</code>: <ul><li><code>.Rprofile</code> - A file run by RStudio every time you load or reload an R session. It calls the <code>renv/activate.R</code> file.</li><li><code>renv/.gitignore</code> - Tells Git to ignore the <code>library</code> folder, as it contains dependencies that can be large in size. There's no need to keep track of them, as the correct version can easily be downloaded by your coworkers.</li><li><code>renv/activate.R</code> - A file used to activate a local R environment.</li><li><code>renv/library/*</code> - Folder with many subfolders - contains the project dependencies.</li></ul> And with that out of the way, let's discuss an essential R <code>renv</code> topic - <b>snapshots</b>. <h2 id="snapshots">How to Take Snapshots of your R Environment</h2> A snapshot is a term used by <code>renv</code> determine dependencies used in your R project and write them to a separate file - <code>renv.lock</code>. You'll see how it works in a second, but first, let's install some R packages: <pre><code class="language-shell">install.packages("dplyr") install.packages("plotly") </code></pre> <img class="size-full wp-image-15955" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f02717ff6b6aa116d24_4.webp" alt="Image 4 - Installing R packages" width="1347" height="1008" /> Image 4 - Installing R packages Once the packages are installed, take a snapshot by running the following line from the R console: <pre><code class="language-r">renv::snapshot()</code></pre> <img class="size-full wp-image-15957" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f03a2fe7aed59a037a5_5.webp" alt="Image 5 - Taking an environment snapshot" width="1347" height="1008" /> Image 5 - Taking an environment snapshot Specify that you want to proceed by typing <code>y</code> when prompted, and you're good to go! A new file named <code>renv.lock</code> is now created, containing all project dependencies and sub-dependencies with the correct version: <img class="size-full wp-image-15959" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f0468667022e1d6bbed_6.webp" alt="Image 6 - Contents of the renv.lock file" width="1347" height="1008" /> Image 6 - Contents of the renv.lock file The file is almost empty (the only dependency being <code>renv</code>), so <b>what gives? </b>Well, as said earlier, <code>renv</code> will store only the dependencies <b>used</b> in your project. Since there's no R code importing either <code>dplyr</code> or <code>plotly</code>, they weren't added to the lock file. Let's change that by making an R file that will render a chart. We've copied some code from the <a href="https://plotly.com/r/bar-charts/" target="_blank" rel="nofollow noopener">Plotly documentation</a>, and encourage you to do the same: <pre><code class="language-r">library(plotly) <br>x <- c("Product A", "Product B", "Product C") y <- c(20, 14, 23) y2 <- c(16, 12, 27) text <- c("27% market share", "24% market share", "19% market share") data <- data.frame(x, y, y2, text) <br>fig <- data %>% plot_ly() fig <- fig %>% add_trace( x = ~x, y = ~y, type = "bar", text = y, textposition = "auto", marker = list( color = "rgb(158, 202, 225)", line = list(color = "rgb(8, 48, 107)", width = 1.5) ) ) fig <- fig %>% add_trace( x = ~x, y = ~y2, type = "bar", text = y2, textposition = "auto", marker = list( color = "rgb(58, 200, 225)", line = list(color = "rgb(8, 48, 107)", width = 1.5) ) ) fig <- fig %>% layout( title = "January 2013 Sales Report", barmode = "group", xaxis = list(title = ""), yaxis = list(title = "") ) <br>fig</code></pre> Here's the figure displayed by Plotly: <img class="size-full wp-image-15961" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f0468667022e1d6bc30_7.webp" alt="Image 7 - A Plotly bar chart" width="1056" height="837" /> Image 7 - A Plotly bar chart You can now once again take the snapshot: <pre><code class="language-r">renv::snapshot()</code></pre> <img class="size-full wp-image-15963" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f05492b6bd1d0b636c3_8.webp" alt="Image 8 - Taking an environment snapshot (2)" width="1347" height="1008" /> Image 8 - Taking an environment snapshot (2) And take a look at the lock file: <img class="size-full wp-image-15965" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f06fe27e3c1e39bac8a_9.webp" alt="Image 9 - Contents of the renv.lock file (2)" width="1347" height="1008" /> Image 9 - Contents of the renv.lock file (2) As you can see, there are many dependencies listed, but we've used only one - <code>plotly</code>. The reason is simple, <code>plotly</code> needs a handful of packages in order to work, and each of these packages has its own dependencies. You can now see how quickly dependency management can become a nightmare. <b>But how easy it is now for other developers to recreate this environment?</b> To answer this question, we have to put ourselves in the shoes of other developers. <h3>Pushing Your R Project to GitHub</h3> This will allow us to clone the project and start fresh (just as you weren't the author of the code), and determine if dependency management with <code>renv</code> really works. Start by creating a new repository on <a href="https://github.com" target="_blank" rel="nofollow noopener">GitHub</a>: <img class="size-full wp-image-15967" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f0626ca1c8b1fa7b3ba_10.webp" alt="Image 10 - A new GitHub repo" width="1224" height="996" /> Image 10 - A new GitHub repo Initialize the R project folder as a Git project, and push it to a remote with the following set of commands: <pre><code class="language-shell">git init git add . git commit -m "initial commit" git remote add origin https://github.com/<you>/<project>.git git push -u origin main</code></pre> <img class="size-full wp-image-15969" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f0767e21dfc9ec2c172_11.webp" alt="Image 11 - Pushing a local project to a remote" width="1281" height="752" /> Image 11 - Pushing a local project to a remote Assuming you did everything correctly, you'll see the R project pushed to the Main branch: <img class="size-full wp-image-15971" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f07a47a6c81522854a2_12.webp" alt="Image 12 - GitHub repo after the initial push" width="1224" height="996" /> Image 12 - GitHub repo after the initial push Next, let's <b>restore</b> this R environment to test if dependency management works as advertised. <h2 id="restore">How to Restore your R Environment with a Single Command</h2> Let's start by cloning the repository into a new folder - <code>NewRenvProject</code>: <pre><code class="language-shell">git clone https://github.com/<you>/<project>.git NewRenvProject</code></pre> <img class="size-full wp-image-15973" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f08717ff6b6aa11710b_13.webp" alt="Image 13 - Cloning a project from GitHub" width="1281" height="752" /> Image 13 - Cloning a project from GitHub As soon as you open it as a project in RStudio, you'll see the message from <code>renv</code> telling you how to restore the environment: <img class="size-full wp-image-15975" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f08c94ac8aeb3b36d5f_14.webp" alt="Image 14 - Opening a new project in RStudio" width="1347" height="1008" /> Image 14 - Opening a new project in RStudio Just run the following command: <pre><code class="langauge-r">renv::restore()</code></pre> And you'll be good to go: <img class="size-full wp-image-15977" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b29f09337d6008eabcc34b_15.webp" alt="Image 15 - Restoring an R environment with renv" width="1347" height="1008" /> Image 15 - Restoring an R environment with renv The R environment is now restored and you have access to all dependencies at the correct version, just as intended by the project author. <hr /> <h2 id="summary">Summing up R renv</h2> And that's how easy it is to manage project package dependencies in R environments. It all boils down to three <code>renv</code> functions - <code>activate()</code>, <code>snapshot()</code>, and <code>restore()</code>. You've learned how each works through a practical example, and by now, we hope you can appreciate the heavy lifting <code>renv</code> does for you. <i>What's your favorite way to manage dependencies in R? Are you still using the outdated <a href="https://rstudio.github.io/packrat/" target="_blank" rel="nofollow noopener">packrat</a> package?</i> Please let us know in the comment section below. Also, don't hesitate to move the discussion to Twitter - <a href="https://twitter.com/appsilon" target="_blank" rel="nofollow noopener">@appsilon</a>. We'd love to hear from you. What do R Shiny developers do? <a href="https://appsilon.com/a-day-in-life-of-an-r-shiny-developer/" target="_blank" rel="noopener">Here's a typical day in the life of Appsilon's Alexandros Kouretsis</a>.