0

I would like to share some some functions that I wrote in R with collegues in form of a an R-package. Those functions rely heavily on other packages and as a practitioneer without programming background, I'm having difficulties to draw a clear line on whether I need to test for a possible error in the usage of the function myself (and create an associated error message) or whether I can just leave this to the error messages of the packages that I'm using.

Here is a small example to make my point clearer:

Multiply_raster <- function(input_raster, multiplication_term) {
  # Test for some things that might go wrong
  if (is.element("raster", installed.packages()[, 1]) == F) {
    stop(
      "You do not have 'raster' installed. Please install the package before proceeding",
      call. = F
    )
  }
  if (class(input_raster) != "RasterLayer") {
    stop("Please provide my_baselayer as an object of Class RasterLayer",
         call. = F)
  }
  if (is.numeric(multiplication_term) == FALSE) {
    stop("Error: Your multiplication term should be numeric", call. = F)
  }
  # load lib
  library(raster)
  # multply multiplication term with input raster
  input_raster * multiplication_term
}

# data for Usage example
library(raster)
raster_example <- raster(matrix(rnorm(400), 20, 20))

First Test

# Error test 1
Multiply_raster(raster_example, "5")

Gives

> Multiply_raster(raster_example, "5")
Error: Error: Your multiplication term should be numeric

Second Test

# Error test 2
Multiply_raster(1:5, 5)

gives

> Multiply_raster(1:5, 5)
Error: Please provide my_baselayer as an object of Class RasterLayer

Alternative specification without error messages

# alternative function specification without own error messages
Multiply_raster_2 <-
  function(input_raster, multiplication_term) {
    # load lib
    library(raster)
    # multply multiplication term with input raster
    input_raster * multiplication_term
  }

First test

# Error test 1
Multiply_raster_2(raster_example, "5")

gives

> Multiply_raster_2(raster_example, "5")
Error in input_raster * multiplication_term : 
  non-numeric argument to binary operator

Second test

# Error test 2
Multiply_raster_2(1:5, 5)

gives

> Multiply_raster_2(1:5, 5)
[1]  5 10 15 20 25

My interpretation: In the first case of the error test I would not necessarily need the logical test and an own error message, because It is quite clear that the multiplication will only work with the correct type of data.

In the case of the second error message, I would need the test because otherwise R still evaluates the function although the input data was not a raster.

Relevance: I ask this because of two things: First, it takes quite some time and ressources to anticipate all possible errors that a user might commit when using the function. Second, I want to avoid redundancy especially if existing error message might be more to the point or better than my own.

I searched for answer on this topic in the tidyverse style-guide and in the Advanced R tips from Hadley Wickham but could not find a clear orientation on this.

joaoal
  • 1,892
  • 4
  • 19
  • 29
  • Just to point out that if you want to check if a package is already installed use [`require`](https://stat.ethz.ch/R-manual/R-patched/library/base/html/library.html). Is faster and more intuitive than the approach you used. Also see [this](https://stackoverflow.com/questions/5595512/what-is-the-difference-between-require-and-library) post. – patL Mar 04 '19 at 08:57
  • 3
    It's not related to the question, but since you're talking about a package it's best to avoid the use of `library`/`require` inside a function. See: http://r-pkgs.had.co.nz/description.html and http://tinyheero.github.io/jekyll/update/2015/07/26/making-your-first-R-package.html – RLave Mar 04 '19 at 08:58
  • 4
    If you build a package, you don't call `library/require` inside the code; rather you declare your dependencies in the `Depends` section of the `DESCRIPTION` file. So you can get rid of checking whether `raster` is installed. The other error is fine to me; it's good practice to check whether the objects passed to a function are what they are supposed to be. As a small tip: use `inherits` rather than `class` to check the class of an object. – nicola Mar 04 '19 at 09:01
  • 2
    Extending @nicola 's comment, use pkgs::function instead of just function to avoid clashes between packages with the same function names. – DJV Mar 04 '19 at 09:13
  • Just a small note: `class() != ***` could case an issue if the object has multiple classes (not sure that'd happen here). `*** %in% class() ` would be safer. – amatsuo_net Mar 04 '19 at 09:28
  • Regarding DVJ's comment, another possibility is to use @importFrom in the function definition if you use roxygen2 for package documentation. See http://kbroman.org/pkg_primer/pages/depends.html – amatsuo_net Mar 04 '19 at 09:36
  • 3
    @amatsuo_net That's the reason why in my comment suggested to use `inherits`, which is still better than using `class` and `%in%`. – nicola Mar 04 '19 at 09:38
  • @nicola. Oh I see. Thanks! – amatsuo_net Mar 04 '19 at 11:56

0 Answers0