<!DOCTYPE html> <html lang="" xml:lang=""> <head> <title>Package management with renv</title> <meta charset="utf-8" /> <meta name="author" content="Jonas Hagenberg" /> <link rel="stylesheet" href="xaringan-themer.css" type="text/css" /> </head> <body> <textarea id="source"> class: center, middle, inverse, title-slide # Package management with <code>renv</code> ### Jonas Hagenberg ### 17.11.2021 --- # What is package management? - control the versions of the packages you use -- - make your analysis reproducible -- - from `R`: `packrat`, from `python`: `venv`, `conda` -- - for every project/analysis, you can use a different set of packages/versions --- # Why `renv`? - newest tool that is under active development by `rstudio` -- - lightweight and easy to get started -- - can be used to support more complicated use cases, e.g. combine containers with a custom library on the cluster --- # How to use it 1. install it: ```r install.packages("renv") ``` -- 2. create a new RStudio project -- 3. initialise `renv`: ```r renv::init() ``` -- 4. work normally on your project, install packages (or update them) -- 5. when you want to save the new status of your packages, use ```r renv::snapshot() ``` ??? do a live presentation here: start a new project, initialise R, install a package, use it in a script, snapshot, look at lockfile --- # How does it work? - `renv` uses a private package library specific for each project -- - the packages are copied from a central `renv` package cache on your computer, so that they don't need to be installed from CRAN every time -- - the package versions are stored in `renv.lock` in a json format. This can be added to version control and others can use the lockfile -- - `renv` automatically discovers which packages are used in your projects (by inspecting `library` calls and `library::function` syntax) ??? this means that it can also be introduced into an already existing project --- # Caveats - only the package & `R` versions are recorded, nothing else (e.g. no system libraries) -- - if you want absolute control, use container -- - recorded package versions could not be available at a later point of time </textarea> <style data-target="print-only">@media screen {.remark-slide-container{display:block;}.remark-slide-scaler{box-shadow:none;}}</style> <script src="https://remarkjs.com/downloads/remark-latest.min.js"></script> <script>var slideshow = remark.create({ "highlightStyle": "github", "highlightLines": true, "countIncrementalSlides": false }); if (window.HTMLWidgets) slideshow.on('afterShowSlide', function (slide) { window.dispatchEvent(new Event('resize')); }); (function(d) { var s = d.createElement("style"), r = d.querySelector(".remark-slide-scaler"); if (!r) return; s.type = "text/css"; s.innerHTML = "@page {size: " + r.style.width + " " + r.style.height +"; }"; d.head.appendChild(s); })(document); (function(d) { var el = d.getElementsByClassName("remark-slides-area"); if (!el) return; var slide, slides = slideshow.getSlides(), els = el[0].children; for (var i = 1; i < slides.length; i++) { slide = slides[i]; if (slide.properties.continued === "true" || slide.properties.count === "false") { els[i - 1].className += ' has-continuation'; } } var s = d.createElement("style"); s.type = "text/css"; s.innerHTML = "@media print { .has-continuation { display: none; } }"; d.head.appendChild(s); })(document); // delete the temporary CSS (for displaying all slides initially) when the user // starts to view slides (function() { var deleted = false; slideshow.on('beforeShowSlide', function(slide) { if (deleted) return; var sheets = document.styleSheets, node; for (var i = 0; i < sheets.length; i++) { node = sheets[i].ownerNode; if (node.dataset["target"] !== "print-only") continue; node.parentNode.removeChild(node); } deleted = true; }); })(); (function() { "use strict" // Replace <script> tags in slides area to make them executable var scripts = document.querySelectorAll( '.remark-slides-area .remark-slide-container script' ); if (!scripts.length) return; for (var i = 0; i < scripts.length; i++) { var s = document.createElement('script'); var code = document.createTextNode(scripts[i].textContent); s.appendChild(code); var scriptAttrs = scripts[i].attributes; for (var j = 0; j < scriptAttrs.length; j++) { s.setAttribute(scriptAttrs[j].name, scriptAttrs[j].value); } scripts[i].parentElement.replaceChild(s, scripts[i]); } })(); (function() { var links = document.getElementsByTagName('a'); for (var i = 0; i < links.length; i++) { if (/^(https?:)?\/\//.test(links[i].getAttribute('href'))) { links[i].target = '_blank'; } } })(); // adds .remark-code-has-line-highlighted class to <pre> parent elements // of code chunks containing highlighted lines with class .remark-code-line-highlighted (function(d) { const hlines = d.querySelectorAll('.remark-code-line-highlighted'); const preParents = []; const findPreParent = function(line, p = 0) { if (p > 1) return null; // traverse up no further than grandparent const el = line.parentElement; return el.tagName === "PRE" ? el : findPreParent(el, ++p); }; for (let line of hlines) { let pre = findPreParent(line); if (pre && !preParents.includes(pre)) preParents.push(pre); } preParents.forEach(p => p.classList.add("remark-code-has-line-highlighted")); })(document);</script> <script> slideshow._releaseMath = function(el) { var i, text, code, codes = el.getElementsByTagName('code'); for (i = 0; i < codes.length;) { code = codes[i]; if (code.parentNode.tagName !== 'PRE' && code.childElementCount === 0) { text = code.textContent; if (/^\\\((.|\s)+\\\)$/.test(text) || /^\\\[(.|\s)+\\\]$/.test(text) || /^\$\$(.|\s)+\$\$$/.test(text) || /^\\begin\{([^}]+)\}(.|\s)+\\end\{[^}]+\}$/.test(text)) { code.outerHTML = code.innerHTML; // remove <code></code> continue; } } i++; } }; slideshow._releaseMath(document); </script> <!-- dynamically load mathjax for compatibility with self-contained --> <script> (function () { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = 'https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-MML-AM_CHTML'; if (location.protocol !== 'file:' && /^https?:/.test(script.src)) script.src = script.src.replace(/^https?:/, ''); document.getElementsByTagName('head')[0].appendChild(script); })(); </script> </body> </html>