R Environment

Environment for R 4.1.

I have forked this notebook from the original R 3.6. I removed the showcase and copy-pasted the R installation procedure for Ubuntu, with DEBIAN_FRONTEND=noninteractive in front of the r-base installation. This accepts the default options and allow the installation code to complete. Also, I skipped the minimal R step to create a more complete (some might say bloated) R environment from a single run.

Setup

The full setup starting from a minimal Ubuntu installation is below

Build a Minimal R Environment

Install R from the R 4.1 repository for Ubuntu. The build-essential package (which includes gcc) is a necessary prerequisite for installation of some R packages.

apt update -qq
# install two helper packages we need
apt install --no-install-recommends software-properties-common dirmngr
# add the signing key (by Michael Rutter) for these repos
# To verify key, run gpg --show-keys /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc 
# Fingerprint: 298A3A825C0D65DFD57CBB651716619E084DAB9
wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | sudo tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc
# add the R 4.0 repo from CRAN -- adjust 'focal' to 'groovy' or 'bionic' as needed
add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/"
DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends r-base
28.2s
DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends r-base
2.5s

Setup package install options.

echo 'local({
  r <- getOption("repos")
  r["CRAN"] <- "https://cloud.r-project.org"
  options(repos = r, download.file.method = "libcurl")
})' > /etc/R/Rprofile.site
0.6s

Install two necessary packages for R to work on Nextjournal.

R -e 'install.packages(c("base64enc", "jsonlite"), Ncpus=4)'
8.0s

Build the Default R Environment

Install

Install libraries that R needs for compilation of packages.

apt-get -qq update
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends \
  libssh2-1 libcurl4-openssl-dev libssl-dev libxml2-dev \
  r-base-dev libcairo2-dev libpango1.0-dev libpangocairo-1.0
apt-get clean
rm -r /var/lib/apt/lists/*
18.3s

Install the conda Jupyter package, then ensure jupyter-client and jupyter-core are the latest releases. Jupyter-core devel used to address connection file permissions issue, revert when 4.6.2 is released. —MPD 15 Dec 2019

conda install jupyter
conda clean -qtipy
pip install --upgrade jupyter-client \
  git+https://github.com/jupyter/jupyter_core
27.4s

This default image has support for tidyverse, plotly, svglite, and shiny. The package also makes some basic utilities available, as well as devtools to help facilitate the use of certain packages, and packrat and renv for installations. Remaining packages are installed to support the Jupyter IRkernel.

R -e 'install.packages(c("devtools", "remotes", "packrat", "renv", 
                   "tidyverse", "uuid", "digest", 
                   "plotly", "svglite", "shiny",
                   "feather", "arrow", "R.matlab", "repr", "future", "evaluate", 
                   "pbdZMQ", "crayon", "IRdisplay", "IRkernel"), 
                 Ncpus=4)'
672.1s
R -e 'IRkernel::installspec()'
2.1s

Setup default fonts for built-in plots, and when ggplot2 and/or svglite are loaded. This .Rprofile will be mounted to root's home directory, and saved with the environment.

R -e 'local({
  if (file.exists("/usr/share/fonts/truetype/Fira_Sans") || 
      file.exists("/usr/share/fonts/truetype/dejavu")) {
    fonts <- "Fira Sans,PT Sans,Open Sans,DejaVu Sans,sans-serif"
  } else {
    fonts <- "sans"
  }
  options(nextjournal.svg.device.default.fonts = fonts)
})
setHook(packageEvent("ggplot2", "onLoad"), 
  function(pkgname,pkgpath) {
    if (file.exists("/usr/share/fonts/truetype/Fira_Sans") || 
        file.exists("/usr/share/fonts/truetype/dejavu")) {
      fonts <- "Fira Sans,PT Sans,Open Sans,DejaVu Sans,sans-serif"
    } else {
      fonts <- "sans"
    }
    options(nextjournal.ggplot.device.default.fonts = fonts)
    ggplot2::theme_update(text = ggplot2::element_text(family = fonts))
  })
setHook(packageEvent("svglite", "onLoad"), 
  function(pkgname,pkgpath) {
    # Function to build a font alias with all four standard faces, 
    # needed because font filenames are not standardized.
    faces <- function(fam,base,r,i,b,bi) {
      list(plain = list(alias = fam, file = paste0(base,r)),
          italic = list(alias = fam, file = paste0(base,i)),
            bold = list(alias = fam, file = paste0(base,b)),
      bolditalic = list(alias = fam, file = paste0(base,bi)))
    }
    if (file.exists("/usr/share/fonts/truetype/Fira_Sans") && 
        file.exists("/usr/share/fonts/truetype/PT_Serif")) {
      fonts <- list(
        sans = faces("Fira Sans,PT Sans,Open Sans,DejaVu Sans,sans-serif",
                     "/usr/share/fonts/truetype/Fira_Sans/FiraSans-",
                     "Regular.ttf","Italic.ttf",
                     "Bold.ttf","BoldItalic.ttf"),
       serif = faces("PT Serif,Noto Serif,DejaVu Serif,serif",
                     "/usr/share/fonts/truetype/PT_Serif/PT_Serif-Web-",
                     "Regular.ttf","Italic.ttf",
                     "Bold.ttf","BoldItalic.ttf"))
    } else { # Fallback for older environments which only had DejaVu fonts
      fonts <- list(
        sans = faces("DejaVu Sans,Fira Sans,PT Sans,Open Sans,sans-serif",
                     "/usr/share/fonts/truetype/dejavu/DejaVuSans",
                     ".ttf","-Oblique.ttf",
                     "-Bold.ttf","-BoldOblique.ttf"),
       serif = faces("DejaVu Serif,PT Serif,Noto Serif,serif",
                    "/usr/share/fonts/truetype/dejavu/DejaVuSerif",
                    ".ttf","-Italic.ttf",
                     "-Bold.ttf","-BoldItalic.ttf"))
    }
    options(nextjournal.svglite.device.default.fonts = fonts)
  })'
1.0s

Cleanup.

rm -rf /tmp/*
0.7s

Checks.

du -hsx /
jupyter kernelspec list
2.2s

Test

R -e 'strsplit(R.version.string," ")[[1]][[3]]'
1.0s
0.6s
Runtimes (1)