Bash equivalent of which in R - r

Is there a function in R to identify which library a package is installed in? (This is assuming that some packages are installed in a local directory, such as ~/R_libs)
For example, in bash one can simply input which [package name] and it will return the location that the [package name] is executing from.

I think you want find.package().
## path to package
find.package("base")
# [1] "/usr/lib/R/library/base"
## path to directory
dirname(find.package("base"))
# [1] "/usr/lib/R/library"

To find, for example, the path to package base (replace this with whichever package you want)
libs <- library()$results
libs[which (libs[,"Package"]=="base"), "LibPath"]

Here is another method using installed.packages:
You can find the path to the package library with the following:
# return a matrix of p by 16 where p is the number of packages you have installed
packageInfo <- installed.packages()
# pull out the path of the library where data.table is installed, for example:
packageInfo["data.table", "LibPath"]
[1] "<path from root>/R/win-library/3.2"
As mentioned in the comments by #procrastinatus-maximus, it would be more compact to use
installed.packages()["data.table", "LibPath"]
Calling installed.packages() causes R to hiccup (a super short delay), so if you are looking up multiple packages, or looking up further information about the packages, then saving the resulting matrix in a variable and pulling info from it directly has tended to be a little more pleasant in my experience.

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 to quickly replicate/update local library under $R_LIBS_USER?

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]))
}

Determine version of a specific package

How can I get the version number for a specific package?
The obvious way is to get the dictionary with all installed packages, and then filter for the one of interest:
pkgs = Pkg.installed();
pkgs["Datetime"]
Getting the list of all installed packages is very slow though, especially if there are many packages.
EDIT: For Julia version 1.1+
Use the Pkg REPL notation:
] status # Show every installed package version
] status pkgName # Show the specific version of the package
] status pkgName1 pkgName2 # Show the named packages. You can continue the list.
The ] enters the Pkg REPL, so you basically write status ...
So in your case, write after entering the Pkg REPL:
status DataFrame
Or use the object-oriented approach (NB: Here you don't enter the Pkg REPL, i.e. DON'T use ]:
Pkg.status("DataFrame")
EDIT: For Julia version 1.0
Pkg.installed seems to have "regressed" with the new package system. There are no arguments for Pkg.installed. So, the OP's original method seems to be about the best you can do at the moment.
pkgs = Pkg.installed();
pkgs["Datetime"]
EDIT: For Julia version upto 0.6.4
You can pass a string to Pkg.installed. For example:
pkgs = Pkg.installed("JuMP")
I often check available calling arguments with methods. For example:
julia> methods(Pkg.installed)
# 2 methods for generic function "installed":
installed() at pkg/pkg.jl:122
installed(pkg::AbstractString) at pkg/pkg.jl:129
or
julia> Pkg.installed |> methods
# 2 methods for generic function "installed":
installed() at pkg/pkg.jl:122
installed(pkg::AbstractString) at pkg/pkg.jl:129
I would try Pkg.status("PackageName")
This will print out a little blurb giving the package name.
Here is an example
julia> Pkg.status("QuantEcon")
- QuantEcon 0.0.1 master
In Julia 1.1 you can use
(v1.1) pkg> status "name_of_the_package"
to find the version of any package in a given environment.
In order to look of a version of an indirectly included package (e.g. top-level project includes Module A which depends on Module B, where you need to know info about Module B), you have to pull the info either from the Manifest.toml directly, or you have to bring in the Context object in from Pkg.
Below is done with Julia 1.3.1 ... there may be changes to Pkg's internals since then.
using Pkg
ctx = Pkg.Operations.Context()
# Get the version of CSV.jl
version = ctx.env.manifest[UUID("336ed68f-0bac-5ca0-87d4-7b16caf5d00b")].version
if version <= v"0.5.24"
# handle some uniqueness about the specific version of CSV.jl here
end
UPDATE: Or without a UUID and just the package name (thanks #HHFox):
using Pkg
pkg_name = "Observables"
m = Pkg.Operations.Context().env.manifest
v = m[findfirst(v->v.name == pkg_name, m)].version
or to do the same with the Manifest.toml
using Pkg
# given the path to the Manifest.toml file...
manifest_dict = Pkg.TOML.parsefile(manifest_path)
# look for a named package like `CSV`
package_dict = manifest_dict[package_name][1]
#show package_dict
Well this didn't print well in the comment section...
Here is a version that matches the name rather than the UUID
using Pkg
m = Pkg.Operations.Context().env.manifest
v = m[findfirst(v -> v.name == "CSV", m)].version
For packages which are dependencies of the specified packages in the project file one can use status -m <packageName> or shorter st -m <packageName> in package mode (After ]`).
For a full list, just use st -m.
This is an extension to https://stackoverflow.com/a/25641957.

How do I set R_LIBS_SITE on Ubuntu so that .libPaths() is set properly for all users at startup?

I am setting up a cluster where all nodes have access to /nfs/software, so a good place to install.packages() would be under /nfs/software/R. How do I set R_LIBS_SITE so that this is automatically part of all users' R environment? I tried prepending to the path given for R_LIBS_SITE in /etc/R/Renviron but help(Startup) says "do not change ‘R_HOME/etc/Renviron’ itself", which I'm not sure is the same file since R_HOME expands to /usr/lib/R, but has no effect in any case. Making entries in the various Renviron.site and Rprofile.site files does not seem to have the desired effect. What am I missing here?
Some other questions have danced around this (here and here, maybe others), but people seem to settle for having a user-specific library in their HOME.
Make sure you have owner and/or group write permissions for the directory you want to write into.
The file /etc/R/Renviron.site is the preferred choice for local overrides to /etc/R/Renviron.
Another way is to simply ... impose the directory when installing packages. I tend to do that on the (bash rather than R) shell via this script derived from an example in the littler package:
$ cat bin/install.r
#!/usr/bin/env r
#
# a simple example to install one or more packages
if (is.null(argv) | length(argv)<1) {
cat("Usage: installr.r pkg1 [pkg2 pkg3 ...]\n")
q()
}
## adjust as necessary, see help('download.packages')
repos <- "http://cran.us.r-project.org"
#repos <- "http://cran.r-project.org"
## this makes sense on Debian where no packages touch /usr/local
lib.loc <- "/usr/local/lib/R/site-library"
install.packages(argv, lib.loc, repos)
and you can easily customize a helper like this for your preferred location. With the script installed in ~/bin/, I often do
$ ~/bin/install.r xts plyr doRedis
and it will faithfully install these packages along with their depends. The littler package has a similar script update.r.
follow-up on Dirk Eddelbuettel (thanks Dirk!)
an adaptation of Dirk's suggestion that may be run within R:
# R function to install one or more packages
Rinstall <- function(pkg) {
if (is.null(pkg) | length(pkg)<1) {
q()
}
if(.Platform$OS.type == "windows") {
lib.dir <- "c:/R/library"
} else {
lib.dir <- "~/R/library"
}
repos.loc <- "http://cran.us.r-project.org"
install.packages(pkg, lib.dir, repos.loc, dependencies=c('Depends','Suggests')) # make sure you get dependencies
}
Usage:
Rinstall(c("package1", "package2"))
Naturally you want to adapt the repos.loc and lib.dir based on your system. As I work on both Windows and Linux machines I also inserted a conditional statement to check which system I'm on.
P.S. Don't hesitate to simplify the code, I'm a total newbie.

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