How to quickly replicate/update local library under $R_LIBS_USER? - r

Suppose that
the version of R I have installed is 3.3.1;
my environment variable $R_LIBS_USER is set to $HOME/my/R_lib/%V; and
I have a directory $HOME/my/R_lib/3.3.1 containing a large number of packages I've installed over time.
Now I want to upgrade my version of R, to 3.4.1, say.
I'm looking for a convenient way to install a new collection of packages under the new directory $HOME/my/R_lib/3.4.1 that is the "version-3.4.1-equivalent" of the library I currently have under $HOME/my/R_lib/3.3.1.
(IOW, I'm looking for a functionality similar to what one can do with Python's pip installer's "freeze" option, which, essentially, produces the input one would have to give the installer in the future to reproduce the current installation.)

You can use function installed.packages for that purpose. Namely:
installed.packages(lib.loc = "$HOME/my/R_lib/3.3.1")
The returned object contains a lot of informations (most fields from each package DESCRIPTION file) but the names of the packages are in the first column. So something like the following should do the trick:
inst <- installed.packages(lib.loc = "$HOME/my/R_lib/3.3.1")
install.packages(inst[,1], lib="$HOME/my/R_lib/3.4.1", dependencies=FALSE)
To answer the additional question in the comments:
If your old library contained packages from other sources than CRAN, you will have to do some gymnastic based on the content of the DESCRIPTION files, and thus will depend on how well the package author documented it.
Argument field in installed.packages allows you to select some additional fields from those files. Fields of interest to determine the source of a package are fields Repository, URL and Maintainer. Here are some ideas on how to split them apart:
CRAN vs non-CRAN:
inst <- installed.packages(lib.loc = "$HOME/my/R_lib/3.3.1",
fields=c("URL","Repository","Maintainer"))
inst <- as.data.frame(inst, row.names=NA, stringsAsFactors=FALSE)
cran <- inst[inst$Repository%in%"CRAN",]
non_cran <- inst[!inst$Repository%in%"CRAN" & !inst$Priority%in%"base",]
Bioconductor packages:
bioc <- inst[grepl("Bioconductor",inst$Maintainer),]
source("https://bioconductor.org/biocLite.R")
biocLite(pkgs=bioc$Packages)
Github packages:
git <- non_cran[grepl("github", non_cran$URL),]
install.packages("devtools")
library(devtools)
for(i in seq(nrow(git))){
install_github(repo=gsub("http://github.com/","",git$URL[i]))
}

Related

Using R, is there a function/library that parses the DESCRIPTION file into a list object?

MOTIVATION
I am wanting to build a PACKAGE-RANKING algorithm based on various measures of optimality.
I was reading something today [tidyverse], that pointed to the following command:
ELEMENT
tools::package_dependencies(package="liteq", recursive=TRUE)[["liteq"]]
Which could easily be wrapped into a function (WORK IN PROGRESS):
help.packageInfo = function(package, key="dependencies", ...)
{
# number of authors
# function to PARSE DESCRIPTION FILE
tools::package_dependencies(package=package, recursive=TRUE)[[package]];
}
EXAMPLE [GOOD]
help.packageInfo("digest");
EXAMPLE [BAD]
help.packageInfo("tidyverse");
HOW to extract DESCRIPTION file data
Package: tools
Version: 4.2.1
Priority: base
Title: Tools for Package Development
Author: R Core Team
Maintainer: R Core Team <do-use-Contact-address#r-project.org>
Contact: R-help mailing list <r-help#r-project.org>
Description: Tools for package development, administration and documentation.
License: Part of R 4.2.1
Suggests: codetools, methods, xml2, curl, commonmark, knitr, xfun,
mathjaxr
NeedsCompilation: yes
Built: R 4.2.1; x86_64-w64-mingw32; 2022-06-23 09:27:10 UTC; windows
ExperimentalWindowsRuntime: ucrt
The description file can tell me lots of things (number of authors, number of suggests, imports, requires) even for NON-CRAN repositories I have installed onto my system. I am trying to ask, is their a library/function that you have seen that parses the DESCRIPTION file into a list object?
In the comments it is pointed out that
pkg <- "stats"
packageDescription(pkg)
is even shorter.
If what you have is not an installed package but rather just a DESCRIPTION file then use the read.dcf shown below.
Assuming that the package is installed get the path to the DESCRIPTION file and then use read.dcf giving a one row matrix whose columns hold the data.
pkg <- "stats"
desc_path <- system.file("DESCRIPTION", package = pkg)
m <- read.dcf(desc_path)
That could be used as is or converted into various forms depending on what you want.
DF <- as.data.frame(m) # one row data.frame
stack(DF) # 2 column data.frame
as.list(DF) # named list
unlist(DF) # named character vector

How do I force installation of R package from custom repo?

There's a dependency of dependency which fails to compile when pulled from CRAN at the moment, so the maintainer provided an alternative Cannot compile RcppArmadillo.
I've tried to install RcppArmadillo from that path like so:
if(!require("RcppArmadillo")) install.packages("RcppArmadillo", repos="https://rcppcore.github.io/drat", lib = LIB_PATH)
library(RcppArmadillo)
if(!require("sqjin/scAI")) devtools::install_github("sqjin/scAI", lib = LIB_PATH)
library(scAI, lib.loc = LIB_PATH)
However, I can see in the logs that RcppArmadillo is still being pulled from CRAN.
How do I force the installation from custom repo?
By setting your options("repos") (named vector) argument in one of your (user or system) startup files you make the alternate location known to R. After that R will pick the highest (== "newest") version (number).
Here is a block from help(Startup) showing one way to do it:
## Example of Rprofile.site
local({
# add MASS to the default packages, set a CRAN mirror
old <- getOption("defaultPackages"); r <- getOption("repos")
r["CRAN"] <- "http://my.local.cran"
options(defaultPackages = c(old, "MASS"), repos = r)
## (for Unix terminal users) set the width from COLUMNS if set
cols <- Sys.getenv("COLUMNS")
if(nzchar(cols)) options(width = as.integer(cols))
# interactive sessions get a fortune cookie (needs fortunes package)
if (interactive())
fortunes::fortune()
})
where you could just use
r["CRAN"] <- "https://cloud.r-project.org"
r["Rcpp"] <- "https://RcppCore.github.io/drat"
As the RcppCore repo is a drat repo you could also consult the drat documentation which has other examples and helpers.

Get the list of installed packages by user in R

How we can get the list of installed packages by user in R along with its version?
I know about the command installed.packages() which will give information about all packages (base or non-base). But how we can get those installed by user to have something like this:
Package Version
X 3.01
Y 2.0.1
Z 1.0.2
For all user installed packages (i.e. those package you installed via install.packages("X"))
ref
ip = as.data.frame(installed.packages()[,c(1,3:4)])
ip = ip[is.na(ip$Priority),1:2,drop=FALSE]
ip
I just found another ways to see the list of the packages without writing any code:
Open RStudio
Navigate to Help --> R Help (from the menu above)
You will see the help panel opened.
Then follow, Reference --> Packages
There you are.
OR
Open R console
Navigate to Help --> Html help
Then follow, Reference --> Packages
str(allPackage <- installed.packages(.Library, priority = "high"))
allPackage [, c(1,3:5)]
You will get all the active package List
Here's my solution.
tibble::tibble(
Package = names(installed.packages()[,3]),
Version = unname(installed.packages()[,3])
)
You can even filter some packages that you want to show.
pkg = tibble::tibble(
Package = names(installed.packages()[,3]),
Version = unname(installed.packages()[,3])
)
dplyr::filter(pkg, Package %in% c("tibble", "dplyr"))
If I develop an app or model and want to record the package versions used, I call sessionInfo()
One trick would be to use library() and a window with all the packages will pop up

Uninstall (remove) R package with dependencies

I wanted to try some new package. I installed it, it required a lot of dependencies, so it installed plenty of other packages. I tried it and I am not impressed - now I would like to uninstall that package including all the dependencies!
Is there any way to remove given packages including all dependencies which are not needed by any other package in the system?
I looked at ?remove.packages but there is no option to do this.
Here is some code that will all you to remove a package and its unneeded dependencies. Note that its interpretation of "unneeded" dependent packages is the set of packages that this package depends on but that are not used in any other package. This means that it will also default to suggesting to uninstall packages that have no reverse dependencies. Thus I've implemented it as an interactive menu (like in update.packages) to give you control over what to uninstall.
library("tools")
removeDepends <- function(pkg, recursive = FALSE){
d <- package_dependencies(,installed.packages(), recursive = recursive)
depends <- if(!is.null(d[[pkg]])) d[[pkg]] else character()
needed <- unique(unlist(d[!names(d) %in% c(pkg,depends)]))
toRemove <- depends[!depends %in% needed]
if(length(toRemove)){
toRemove <- select.list(c(pkg,sort(toRemove)), multiple = TRUE,
title = "Select packages to remove")
remove.packages(toRemove)
return(toRemove)
} else {
invisible(character())
}
}
# Example
install.packages("YplantQMC") # installs an unneeded dependency "LeafAngle"
c("YplantQMC","LeafAngle") %in% installed.packages()[,1]
## [1] TRUE TRUE
removeDepends("YplantQMC")
c("YplantQMC","LeafAngle") %in% installed.packages()[,1]
## [1] FALSE FALSE
Note: The recursive option may be particularly useful. If package dependencies further depend on other unneeded packages, setting recursive = TRUE is vital. If dependencies are shallow (i.e., only one level down the dependency tree), this can be left as FALSE (the default).
There is in fact a function remove.packages() in base R, but it's in the package utils, which you need to load first:
library(utils)
remove.packages()
It's not entirely clear to me how much recursive cleanup this function does.
There are base R ways to handle this but I'm going to recommend a package (I know you're trying to get rid of these). I'm recommending this package for 2 reasons (1) it solves two problems you're having & (2) Dason K. and I are developing this package (full disclosure). This package's value stands in that the functions are easier to remember names that are consistent. It also does some combined operations. Note you could do all of this in base but this question is already pretty localized so thus I'm going to use a tool that makes answering easier.
This package will:
allow you to delete package and dependencies
allow you to install packages in a temporary directory rather than main library
The caveat is that you can't be 100% certain that the package dependency wasn't already there, installed by the user previously. Therefore I would take caution with every step of this solution that you're not deleting things that are of importance. This solution relies on 2 factors (1) pacman (2) file.info. We'll assume that dependencies that were modified within a certain (user defined) threshold of time are indeed unwanted packages. Note the word assume here.
I made this reproducible for the folks at home in that the answer will randomly install a package from CRAN with additional dependencies (this installs a package you do not already have locally with 3 or more dependencies; used random to not single out any package).
Making a reproducible example
library(pacman)
(available <- p_cran())
(randoms <- setdiff(available, p_lib()))
(mypackages <- p_lib())
ndeps <- 1
while(ndeps < 3) {
package <- sample(randoms, 1)
deps <- unlist(p_depends(package, character.only=TRUE), use.names=FALSE)
ndeps <- length(setdiff(deps, mypackages))
}
package
p_install(package, character.only = TRUE)
Uninstalling package
We will assign the package name from the first part to package or the OP can use the unwanted package they installed and assign that to package (my random package happened to be package <- "OrdinalLogisticBiplot"). This deletions process should, ideally, be done in a clean R session with no add-on packages (except pacman) loaded.
## function to grab file info date/time modified
infograb <- function(x) file.info(file.path(p_path(), x))[["mtime"]]
## determine the differences in times modified for "package"
## and all other packages in library
diffs <- as.numeric(infograb(package)) - sapply(p_lib(), infograb)
## user defined threshold
threshold <- 15
## determine packages just installed within the time frame of the unwanted package
(delete_deps <- diffs[diffs < threshold & diffs >= 0])
## recursively find all packages that could have been installed
potential_depends <- unlist(lapply(unlist(p_depends(package, character=TRUE)),
p_depends, character=TRUE, recursive=TRUE))
## delete packages that are both on the lists of (1) installed within time
## frame of unwanted package and a dependency of that package
p_delete(intersect(names(delete_deps), potential_depends), character.only = TRUE)
This approach makes some big assumptions.
A better approach from the get go
p_temp(package_to_try)
This allows you to try it out first and not have it muddy your local library.
If you're unimpressed with pacman you can use the method described above to delete it.
Here is a quick solution to have a look at the packages that are not required by any other locally installed packages.
library(pacman)
ip <- installed.packages()[,1]
deps <- lapply(1:length(ip), function(i) tryCatch(p_depends(ip[i], local = TRUE)$Imports, error = function(e) return(NULL)))
packages.on.which.things.depend <- sort(unique(unlist(deps)))
packages.on.which.nothing.depends <- setdiff(ip, packages.on.which.things.depend)
packages.on.which.nothing.depends
Then, have a quick look at it and remove the ones you are not using (just be careful and do not try to uninstall base).
After you have determined which ones you use and which you don’t use, you may proceed with something like
i.need <- c("AER", "car", "devtools", "glmnet", "gmm", "Hmisc", "pacman", "plm", "RcppArmadillo", "RcppEigen", "rmarkdown", "rugarch", "base", "datasets")
un <- setdiff(packages.on.which.nothing.depends, i.need)
un
remove.packages(un)
Rinse and repeat until there are no unneeded orphanes packages. R should not allow you to remove built-in system packages.

Installing all CRAN packages that are not already installed?

The following R commands will install all CRAN packages:
availablePackages <- available.packages()[,1]
install.packages(availablePackages)
And the following command will list all installed packages:
installedPackages <- .packages(all.available = TRUE)
My question is: How do I instruct R to install all CRAN packages that are not already installed?
Frankly, I think it's painstaking job... it would last for days, even weeks (depending on resources), but here's the code (I just enjoy doing trivial things):
# get names of installed packages
packs <- installed.packages()
exc <- names(packs[,'Package'])
# get available package names
av <- names(available.packages()[,1])
# create loooong string
ins <- av[!av %in% exc]
install.packages(ins)
I still don't get why you're doing this, but, hey... some things are just not meant to be....
What wonders me the most is the fact that you've already answered your own question! You got what you needed, and it's just up to you to put things together...
Are we missing the point? Did you have something else in mind?!?
1) Why would you want to do that? There are over 3500 (as of Feb 2012) of them?
2) Did you look at CRAN Task Views and the ctv package that allows you to install packages from a given task?
3) You bold-face question is a simple indexing query you can do by hand (and besides that, also see help(sets))
R> available <- LETTERS # a simple set
R> installed <- LETTERS[c(1:10, 15:26)] # a simple subset
R> available[ ! available %in% installed ]
[1] "K" "L" "M" "N"
R>
Edit: in response to your follow-up:
a) If a package does not pass 'R CMD check' on Linux and Windows, it does not get uploaded to CRAN. So that job is done.
b) Getting all depends at your end is work too as you will see. We did it for cran2deb which is at http://debian.cran.r-project.org (which does full-blown Debian package building which is more than just installing). We get about 2050 out of 2150 packages built. There are a few we refuse to build because of license, a few we cannot because of missing headers or libs and a few we cannot build because they need e.g. BioConductor packages.
type this command and then all packages will be installed automatically:
install.packages(available.packages()[,1])
Better if you use:
check.and.install.Package<-function(package_name){
if(!package_name%in%installed.packages()){
install.packages(package_name)
}
}
call the function and check if required package is installed:
check.and.install.Package("pkgName")
I've tested this and it works
availablePackages=available.packages()
availablePackages<-as.vector(availablePackages[,1])
installedPackages=.packages(all.available = TRUE)
missedPackages<-setdiff(availablePackages, installedPackages)
for (i in 1:length(missedPackages))
{
pkgName <- missedPackages[i]
install.packages(pkgName)
}
print("END")
Regards
From my experience, it is not wise to install all the R packages at once! Even if you do not call upon (using library function) all those packages, by just sitting in the home directory, they can slow down your R studio. At least that's what happened in my case.

Resources