Skip to content

Instantly share code, notes, and snippets.

@mikedecr
Last active November 30, 2021 20:42
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikedecr/6fd2e7855c71e4358534d5af3b72a03d to your computer and use it in GitHub Desktop.
Save mikedecr/6fd2e7855c71e4358534d5af3b72a03d to your computer and use it in GitHub Desktop.
When you're installing packages after a major R upgrade and you DON'T just want to get everything from CRAN.
# ----------------------------------------------------
# Installing packages for new R version.
# Michael DeCrescenzo
#
# Hi, I'm a political science PhD student looking for
# a data science/quantitative research/statistics job.
# Learn more at <mikedecr.github.io> and <github.com/mikedecr>
#
# This script deals with the following problem:
# I upgraded to new major version of R, & I want to reinstall packages.
# However I don't simply want to get all installed.packages() from CRAN.
# Why not?
# I may be using an experimental pkg version that is more recent.
# Or the pkg isn't on CRAN at all, so I want to install from Github (e.g.).
#
# This script contains steps to implement the following.
# (I recommend you go through slowly)
#
# 1. Save installed package info (name, version, source/github repo)
# 2. Compare local package versions to what's on CRAN
# to see if I should install from CRAN
# or from some other repository.
# 3. Do the installing (after updating R)
#
# ----------------------------------------------------
# you should be working out of some directory for this.
# For me it's ~/tools/update-R
library("here")
library("tidyverse")
# ---- get install source info from installed packages -----------------------
# data frame of all installed packages
local_pkgs <- installed.packages() %>%
as_tibble() %>%
print()
# get source details (cran, github...) from package_info()
local_details <-
sessioninfo::package_info(pkgs = local_pkgs$Package) %>%
as_tibble() %>%
select(package, local_version = ondiskversion, source) %>%
print()
# you may notice that we have fewer rows now.
# What's in all_pkgs that isn't in locals?
anti_join(local_pkgs, local_details, by = c("Package" = "package"))
# the base packages, which I presume will be fine when updating R.
# ---- compare local pkg versions to CRAN -----------------------
# available.packages() returns pkg info for ALL pkgs on CRAN.
cran_pkgs <- available.packages() %>%
as_tibble(.name_repair = tolower) %>%
print()
# but we only need to compare to what we have locally.
# So we left_join.
# We also determine which package version is more recent.
# Do this using utils::compareVersion().
# Note that if one of the pkg versions is NA, the function infers that
# the other version is more recent.
# This means I'm classifying comparisons into a few groups.
# - Local more recent and source contains "Github":
# => "Github"
# - Local is more recent, source contains "CRAN", but can't find CRAN version:
# => "Unavailable on CRAN"
# - Source contains "CRAN" but CRAN version is lower than local?
# => "Downgraded on CRAN"
# - CRAN is more recent or same as local:
# => "CRAN"
# last step is to store github repositories for the GH packages.
compare_frame <-
left_join(
x = select(local_details, package, local_version, source),
y = select(cran_pkgs, package, cran_version = version)
) %>%
group_by(package) %>%
mutate(
source_locale = case_when(
compareVersion(local_version, cran_version) == 1 &
str_detect(source, "Github") ~ "Github",
compareVersion(local_version, cran_version) == 1 &
is.na(cran_version) &
str_detect(source, "CRAN") ~ "Unavailable on CRAN",
compareVersion(local_version, cran_version) == 1 &
(is.na(cran_version) == FALSE) &
str_detect(source, "CRAN") ~ "Downgraded on CRAN",
compareVersion(local_version, cran_version) %in% c(-1, 0) ~ "CRAN"
),
github_repo = case_when(
source_locale == "Github" ~
str_split(string = source, pattern = "@", simplify = TRUE)[,1] %>%
str_replace("Github \\(", ""),
TRUE ~ as.character(NA)
),
) %>%
ungroup() %>%
print(n = nrow(.))
# see how many packages don't record CRAN as the future install source
compare_frame %>%
filter(source_locale != "CRAN") %>%
arrange(source_locale)
# In my case...
# - StanHeaders got its version downgraded, see <https://github.com/cran/StanHeaders/commit/2294a66cb1876568b6af74a6c4a1233bf6b6e00f>
# - Can't get CRAN info for Zelig or foreign.
# - Rest are Github packages
# ---- save pkg info when satisfied -----------------------
# data location
dir.create(here("data"))
out_file <- as.character(str_glue("pkg-data_{Sys.Date()}.rds"))
write_rds(compare_frame, here("data", out_file))
# ---- this is where you would install new R ------------------
# https://cran.r-project.org/
# ---- reinstall -----------------------
# we need package to install from github
install.packages("remotes")
# should still be operating in your working directory
# so if you want to use {here}, you can.
install.packages("here")
# read package data
pkgs <- readRDS(here::here("data", "pkg-data_2020-04-25.rds"))
head(pkgs)
# install from cran
# using vector of package names
cran_pkgs <- pkgs[pkgs$source_locale != "Github", ][["package"]]
# probably should have excluded rstan tbh.
# I feel like I'm going to regret not taking special care for that one.
install.packages(cran_pkgs)
# install from github
# using vector of github repositories
github_pkgs <-
pkgs[pkgs$source_locale == "Github", ][["github_repo"]]
remotes::install_github(github_pkgs)
@medewitt
Copy link

This is a life-saver. I have used it and shared it multiple times. Thank you!

@medewitt
Copy link

Adding note for myself

github_pkgs <- github_pkgs[!is.na(github_pkgs)]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment