tryCatch() Vs if else - r

I have recently started exploring R programming and have a very trivial doubt. I want to write a function which would try to load the required packages and install the same in case its not installed already.
I have written it using if else logic. My question is will it be more efficient if I use tryCatch()? Is there any other advantage than the ability to handle errors as it is not important to handle errors in this context.
Below is the code I am currently using:
Inst.Pkgs=function(){
if (!require(tm))
{install.packages("tm")
require(tm)}
if (!require(SnowballC))
{install.packages("SnowballC")
require(SnowballC)}
if (!require(wordcloud))
{install.packages("wordcloud")
require(wordcloud)}
if (!require(RWeka))
{install.packages("RWeka")
require(RWeka)}
if (!require(qdap))
{install.packages("qdap")
require(qdap)}
if (!require(timeDate))
{install.packages("timeDate")
require(timeDate)}
if (!require(googleVis))
{install.packages("googleVis")
require(googleVis)}
if (!require(rCharts))
{
if (!require(downloader))
{install.packages("downloader")
require(downloader)}
download("https://github.com/ramnathv/rCharts/archive/master.tar.gz", "rCharts.tar.gz")
install.packages("rCharts.tar.gz", repos = NULL, type = "source")
require(rCharts)
}
}

You can check at once and install missing packages.
# Definition of function out, the opposite of in
"%out%" <- function(x, table) match(x, table, nomatch = 0) == 0
# Storing target packages
pkgs <- c("tm", "SnowballC", "wordcloud", "RWeka", "qdap",
"timeDate", "googleVis")
# Finding which target packages are already installed using
# function installed.packages(). Names of packages are stored
# in the first column
idx <- pkgs %out% as.vector(installed.packages()[,1])
# Installing missing target packages
install.packages(pkgs[idx])

We can in fact use tryCatch for this. If the program tries to load a library that is not installed, it will throw an error - an error that can be caught and resolved with a function called by tryCatch().
Here's how I would do it:
needed_libs <- c("tm", "SnowballC", "wordcloud", "RWeka", "qdap", "timeDate", "googleVis")
install_missing <- function(lib){install.packages(lib,repos="https://cran.r-project.org/", dependencies = TRUE); library(lib, character.only = TRUE)}
for (lib in needed_libs) tryCatch(library(lib, character.only=TRUE), error = function(e) install_missing(lib))
This will install the missing packages and load the required libraries, as requested in the OP.

Related

testthat with lintr::expect_lint_free() fails with devtools::check() but works with devtools::test()

This test in my package works fine with devtools::test(). Also the online Travis build is going well.
test_that("Package style", {
lintr::expect_lint_free()
})
However, with devtools::check() it fails.
The error message is
invalid 'path' argument
Backtrace:
1. lintr::expect_lint_free()
2. lintr::lint_package(...)
3. base::normalizePath(path, mustWork = FALSE)
4. base::path.expand(path)
I'm running R version 3.6.3 (2020-02-29), testthat 2.3.2 and lintr 2.0.1 on Windows.
I think the problem is that lintr doesn't know which file(s) to lintr.
Could somebody please point out to me what the solution to this problem is?
This is known bug with lintr. Currently, the best workaround for it is replacing your code with:
if (requireNamespace("lintr", quietly = TRUE)) {
library(lintr)
context("linting package")
test_that("Package Style", {
# A duplicate copy of the find_package function from lintr
find_package <- function(path) {
path <- normalizePath(path, mustWork = FALSE)
while (!file.exists(file.path(path, "DESCRIPTION"))) {
path <- dirname(path)
if (identical(path, dirname(path))) {
return(NULL)
}
}
path
}
if (!is.null(find_package("."))) {
expect_lint_free()
)
}
})
}
The source for this solution is in that same link.

How to install R and packages through configuration.nix and how to add packages from github?

Two related questions:
1. How does one install R and selected packages in the configuration.nix?
2. How does one add packages not only from CRAN but also from Gitub or at least locally stored?
In the wiki you will find instructions like these to install R packages. https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/r.section.md . Have it working when using nix-shell but I'm stuck while trying to do the installation from configuration.nix.
Regarding building R packages and I have found this example regarding building packages:
let
pkgs = import <nixpkgs> {};
buildRPackage = import <nixpkgs/pkgs/development/r-modules/generic-builder.nix> pkgs.R;
in
with pkgs.rPackages;
{
foobar = buildRPackage {
name = "your-package-name-1.0";
src = ./.;
propagatedBuildInputs = [/* required dependencies go here */];
};
}
The command "nix-build . -A foobar" would then compile it.
But would like to run all from configuration.nix in order to the machine configuration in one place.
Ok, with the help of Bulats pointer above I managed to find a solution. A complete example was found here: https://github.com/NixOS/nixpkgs/issues/44290
For future reference here is one way of adding r packages both from CRAN and Github inline in configuration.nix:
environment.systemPackages = with pkgs;
[(pkgs.rWrapper.override {
packages = with pkgs.rPackages; let
llr = buildRPackage {
name = "llr";
src = pkgs.fetchFromGitHub {
owner = "dirkschumacher";
repo = "llr";
rev = "0a654d469af231e9017e1100f00df47bae212b2c";
sha256 = "0ks96m35z73nf2sb1cb8d7dv8hq8dcmxxhc61dnllrwxqq9m36lr";};
propagatedBuildInputs = [ rlang knitr];
nativeBuildInputs = [ rlang knitr ];};
in [knitr
rlang
llr
tidyverse
## the rest of your R packages here
devtools];})
pkgs.postgresql
pkgs.isync
pkgs.msmtp
pkgs.notmuch
gnupg
## the rest of your Nixos packages (derivations) here
];

NoSuchMethodException when calling sendKeys on object of class org.openqa.selenium.remote.RemoteWebElement via R package rJava

I am trying to use the selenium webdriver API directly from R using rJava. I am subject to a fairly restrictive IT environment, so I can't access a remote driver currently (hence why I'm not currently using the Rselenium package), and I don't have either Chrome or Firefox availaible--just phantomjs. I am able to get this working okay from the Scala REPL. I used sbt to get all the dependenices--build.sbt contains, for example:
retrieveManaged := true
libraryDependencies ++= Seq (
"org.seleniumhq.selenium" % "selenium-java" % "3.9.1",
"com.codeborne" % "phantomjsdriver" % "1.4.4"
)
(Note that I have phantomjs installed as /usr/local/bin/phantomjs, and it is
version 2.1.1).
I then copied all the jar files to a single-level folder via cp jars/*/*/*.jar alljars/ containing the following:
animal-sniffer-annotations-1.14.jar httpcore-4.4.6.jar selenium-api-3.9.1.jar
byte-buddy-1.7.9.jar j2objc-annotations-1.1.jar selenium-chrome-driver-3.9.1.jar
checker-compat-qual-2.0.0.jar jline-2.14.5.jar selenium-edge-driver-3.9.1.jar
commons-codec-1.10.jar jsr305-1.3.9.jar selenium-firefox-driver-3.9.1.jar
commons-exec-1.3.jar okhttp-3.9.1.jar selenium-ie-driver-3.9.1.jar
commons-logging-1.2.jar okio-1.13.0.jar selenium-java-3.9.1.jar
error_prone_annotations-2.1.3.jar phantomjsdriver-1.4.4.jar selenium-opera-driver-3.9.1.jar
gson-2.8.2.jar scala-compiler-2.12.4.jar selenium-remote-driver-3.9.1.jar
guava-23.6-jre.jar scala-library-2.12.4.jar selenium-safari-driver-3.9.1.jar
httpclient-4.5.3.jar scala-reflect-2.12.4.jar selenium-support-3.9.1.jar
I start Scala via scala -cp "alljars/*" and can the do following:
val drv = new org.openqa.selenium.phantomjs.PhantomJSDriver
drv.get("https://www.google.com")
val q = drv.findElementByName("q")
q.sendKeys("rJava selenium")
q.submit
drv.getTitle
I think the following is roughly the same thing in R using rJava:
library(rJava)
.jinit()
jars <- dir("alljars", pattern = "*.jar", full.names = TRUE)
.jaddClassPath(jars)
drv <- .jnew('org/openqa/selenium/phantomjs/PhantomJSDriver')
drv$get("https://www.google.com")
q <- drv$findElementByName("q")
q$sendKeys("rJava selenium")
q$submit()
drv$getTitle()
This fails at the point q$sendKeys("rJava selenium") with the following error:
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl, :
java.lang.NoSuchMethodException: No suitable method for the given parameters
In RStudio, if I type q$ and press TAB, sendKeys is definitely in the list of available methods. I tried to be explicit about this, and tried:
keys <- .jnew("java/lang/String", "rJava selenium")
keys <- .jcast(keys, "java/lang/CharSequence", check = TRUE)
q <- .jcast(q, "org/openqa/selenium/WebElement", check = TRUE)
.jcall(q, "V", "sendKeys", keys)
which resulted in the following error:
Error in .jcall(q, "V", "sendKeys", keys) :
method sendKeys with signature (Ljava/lang/CharSequence;)V not found
q has class org/openqa/selenium/remote/RemoteWebElement in R, and org/openqa/selenium/WebElement in Scala; but in both cases the return is void and the required argument is CharSequence according to the javadocs. I tried a few variations of this--java.lang.String instead of CharSequence, RemoteWebElement instead of WebElement, etc., but no joy.
I doubt this is a problem with rJava, but I'm stumped nonetheless and need help!
Oh good grief. I didn't know about .jmethods. Running this:
> .jmethods(q, "sendKeys")
[1] "public void org.openqa.selenium.remote.RemoteWebElement.sendKeys(java.lang.CharSequence[])"
So, basically, my problem was that I was passing String instead of String[]. That is, instead of:
q$sendKeys("rJava selenium")
I can use:
q$sendKeys(.jarray("rJava selenium"))
The more you know...

Issue with TSO function in tsoutliers

I am trying to get the tso() function of the tsoutliers package to work but I keep running into the same maddening error when the dplyr package is loaded that I can't seem to figure out. Any ideas?
Here is some code from a previous answer that seemed to work only when dplyr is not loaded in the namespace.
dat.change <- c(12.013995263488, 11.8460207231808, 11.2845153487846, 11.7884417180764,
11.6865425802022, 11.4703118125303, 11.4677576899063, 11.0227199625084,
11.274775836817, 11.03073498338, 10.7771805591742, 10.7383206158923,
10.5847230134625, 10.2479315651441, 10.4196381241735, 10.467607842288,
10.3682422713283, 9.7834431752935, 9.76649842404295, 9.78257968297228,
9.87817694914062, 9.3449034905713, 9.56400153361727, 9.78120084558148,
9.3445162813738, 9.36767436354887, 9.12070987223648, 9.21909859069157,
8.85136359917466, 8.8814423003979, 8.61830163359642, 8.44796977628488,
8.06957847272046, 8.37999165387824, 7.98213210294954, 8.21977468333673,
7.683960439316, 7.73213584532496, 7.98956476021092, 7.83036046746187,
7.64496198988985, 4.49693528397253, 6.3459274845112, 5.86993447552116,
4.58301192892403, 5.63419551523625, 6.67847511602895, 7.2005344054883,
5.54970477623895, 6.00011922569104, 6.882667104467, 4.74057284230894,
6.2140437333397, 6.18511450451019, 5.83973575417525, 6.57271194428385,
5.36261938326723, 5.48948831338016, 4.93968645996861, 4.52598133247377,
4.56372558828803, 5.74515428123725, 5.45931581984165, 5.58701112949141,
6.00585679276365, 5.41639695946931, 4.55361875158434, 6.23720558202826,
6.19433060301002, 5.82989415940829, 5.69321394985076, 5.53585871082265,
5.42684812413063, 5.80887522466946, 5.56660158483312, 5.7284521523444,
5.25425775891636, 5.4227645808924, 5.34778016248718, 5.07084809927736,
5.324066161355, 5.03526881241705, 5.17387528516352, 5.29864121433813,
5.36894461582415, 5.07436929444317, 4.80619983525015, 4.42858947882894,
4.33623051506001, 4.33481791951228, 4.38041031792294, 3.90012900415342,
4.04262777674943, 4.34383842876647, 4.36984816425014, 4.11641092254315,
3.83985887104645, 3.81813419810962, 3.85174630901311, 3.66434598962311,
3.4281724860426, 2.99726515704766, 2.96694634792395, 2.94003031547181,
3.20892607367132, 3.03980832743458, 2.85952185077593, 2.70595278908964,
2.50931109659839, 2.1912274016859)
library("tsoutliers")
dat.ts<- ts(dat.change, frequency=1)
data.ts.outliers <- tso(dat.ts)
ERROR I obtain is:
> data.ts.outliers <- tso(dat.ts)
Error in filter_(.data, .dots = lazyeval::lazy_dots(...)):
argument ".data" is missing, with no default
I am fairly certain that the issue is a conflict with dplyr but I am not sure how to get around it easily. If I do not install dplyr everything is peachy and runs.
Any Ideas?
As you say, there is a conflict between stats::filter and dplyr::filter. I fixed it by adding stats::filter as an import in the namespace of package tsoutliers.
The new version of the package is not yet on CRAN, in the meantime you can get the sources from this temporary link and windows binaries from this other link.
I wrote following function that unloads dplyr when calling tso():
replaceOutliers <- function(series) {
require(tsoutliers)
detach("package:dplyr", unload=TRUE)
o <- tso(ts(series))
print(paste("Replacing", length(o$outliers$ind), "outliers for series"))
series <- o$yadj
library(dplyr)
return(series)
}
Absolutely not an elegant solution but I didn't want to go messing in the R code of tsoutliers.

Default .Options setting for unzip

I was trying to install ramnathv's slidify package and was surprised the by the following error:
# install.packages("devtools")
library(devtools)
install_github("slidify","ramnathv")
Installing github repo slidify/master from ramnathv
Downloading slidify.zip from https://github.com/ramnathv/slidify/archive/master.zip
Installing package from /tmp/RtmpOFEJuD/slidify.zip
Error in unzip(src, exdir = target, unzip = getOption("unzip")) :
'unzip' must be a single character string
I've installed it before with no issues on another system using the same Arch Linux setup and their R package, granted it was an earlier version of R (3.0.0 or 3.0.1).
In googling the error, it comes from this bit in zip.R:
unzip <-
function(zipfile, files = NULL, list = FALSE, overwrite = TRUE,
junkpaths = FALSE, exdir = ".", unzip = "internal",
setTimes = FALSE)
{
if(identical(unzip, "internal")) {
if(!list && !missing(exdir))
dir.create(exdir, showWarnings = FALSE, recursive = TRUE)
res <- .External(C_unzip, zipfile, files, exdir, list, overwrite,
junkpaths, setTimes)
if(list) {
dates <- as.POSIXct(res[[3]], "%Y-%m-%d %H:%M", tz="UTC")
data.frame(Name = res[[1]], Length = res[[2]], Date = dates,
stringsAsFactors = FALSE)
} else invisible(attr(res, "extracted"))
} else {
WINDOWS <- .Platform$OS.type == "windows"
if(!is.character(unzip) || length(unzip) != 1L || !nzchar(unzip))
stop("'unzip' must be a single character string")
...
While the default setting for unzip() is unzip = "internal", it can also be passed getOptions("unzip"):
Usage
unzip(zipfile, files = NULL, list = FALSE, overwrite = TRUE,
junkpaths = FALSE, exdir = ".", unzip = "internal",
setTimes = FALSE)
...
unzip
The method to be used. An alternative is to use getOption("unzip"),
which on a Unix-alike may be set to the path to a unzip program.
In looking at the output of .Options, I see, indeed, that there's nothing set for unzip:
> .Options$unzip
[1] ""
From perusing documentation, I see that I can set this in ~/.Renviron, but my question is whether on a Linux system this should be picked up by default or if it's pretty standard to have to set your unzip command?
If it's not standard that this be un-populated, I'll file a bug report with Arch Linux, as perhaps the package was compiled without this as a default, as documentation seems to suggest that it would be populated with an unzip command if one was found during installation:
unzip
a character string, the path of the command used for unzipping help files, or
"internal". Defaults to the value of R_UNZIPCMD, which is set in ‘etc/Renviron’
if an unzip command was found during configuration.
The Arch package I'm using is a binary and thus was pre-compiled, so intentionally or unintentionally perhaps this was overlooked or should be checked for during installation?
P.S. Just to avoid the obvious...
$ which unzip
/usr/bin/unzip

Resources