Help on interpretation of code

Hi all,

I am new to AML studio, and are picking up on R programming. In one of the tutorials about the dataset cadairydata.csv, I was taught the following codes. However, I am unable to dissect the code. Thus, would appreciate if someone can enlighten me.

  1. the argument ‘inver’ appears not declared but it seems ok, how come?
  2. the function appears to be a function to test for error, is it not?
  3. if not doing the error testing, what code would get the same transformation of the value?
log.transform <- function(invec, multiplier = 1) {
  ## Function for the transformation, which is the log
  ## of the input value times a multiplier

  warningmessages <- c("ERROR: Non-numeric argument encountered in function log.transform",
                       "ERROR: Arguments to function log.transform must be greate than zero",
                       "ERROR: Aggurment multiplier to funcition log.transform must be a scaler",
                       "ERROR: Invalid time seies value encountered in function log.transform"
                       )

  ## Check the input arguments
  if(!is.numeric(invec) | !is.numeric(multiplier)) {warning(warningmessages[1]); return(NA)}  
  if(any(invec < 0.0) | any(multiplier < 0.0)) {warning(warningmessages[2]); return(NA)}
  if(length(multiplier) != 1) {{warning(warningmessages[3]); return(NA)}}

  ## Wrap the multiplication in tryCatch
  ## If there is an exception, print the warningmessage to
  ## standard error and return NA
  tryCatch(log(multiplier * invec),
           error = function(e){warning(warningmessages[4]); NA})
}


## Apply the transformation function to the 4 columns
## of the dataframe with production data
multipliers  <- list(1.0, 6.5, 1000.0, 1000.0)
cadairydata[, 4:7] <- Map(log.transform, cadairydata[, 4:7], multipliers)

Hi and welcome to the community!

  1. The Invec argument is simply not given a default. That means taht when you call the function you have to pass your own value to that argument. If you do not pass a value to that argument than the function will not run. Conversely, the multiplier argument has a default value of 1, so if you only passed the invec argument to the function when calling it, then it will still run and use 1 as the multiplier value.
  2. The function certainly has error checking in it, but that is not its main purpose. The purpose of this function is to log transform the data using some multiplier. When writing functions, it is good practice to include error checking steps in order to ensure that the code you are trying to execute correctly is working. We can look at each of these error messages one at a time:
if(!is.numeric(invec) | !is.numeric(multiplier)) {warning(warningmessages[1]); return(NA)}

This line is checking whether the values given to each argument are numeric. If not it returns NA and gives the user a error message

if(any(invec < 0.0) | any(multiplier < 0.0)) {warning(warningmessages[2]); return(NA)}

This line is making sure that none of the values passed to either argument is less than zero because the log of a negative number gives the value of NaN

if(length(multiplier) != 1) {{warning(warningmessages[3]); return(NA)}}

This is ensuring that only a single multiplier is provided

Finally, you get to the actual portion of the code that is doing the desired computation. It is a little confusing because it is in a tryCatch function.

tryCatch(log(multiplier * invec),
           error = function(e){warning(warningmessages[4]); NA})

However, this is just a defensive mechanism for programming. They could have simply put log(multiplier*invec) and returned the result. However, what if their manual error catching didn't capture all of the possible ways that that line of code could fail? The tryCatch function will execute the desired command (in this case log(multiplier*invec)) and if the code executes with no error will return the result. If the code fails however, then it will return a more informative error message and an NA value.

  1. If you wanted to accomplish what this function is doing without the error checking you could simply write:
my_log_trans <- function(invec, multiplier = 1){
  log(multiplier * invec)
}

However, I wouldn't recommend removing the error catching as it was likely put there so that the function would work properly

1 Like

Thank you for your guidance.

While I understand the importance of defensive mechanism, I am trying to understand the underlying function of the code as I understand the error messaging part.

What I cannot comprehend is, how the invec argument is being taken as an input? And what is the value?
I understand the multiplier is set as default 1.
Considering invec is undefine, wouldn’t log (invec * 1) be considered as unknown (Null)?

How the log.function is use via map to connect with the data in cadairydata and the defined list of multipliers?

Throughout the code, I am unable to determine what is invec.:disappointed_relieved:

Hope you can assist to clarify. Thanks in advance

Hi, if you don't name the arguments as you use the function, it treats the first argument as invec and the second as multiplier. See below that these all give the same results (using simple version of function):


my_log_trans <- function(invec, multiplier = 1){
  log(multiplier * invec)
}

my_log_trans(c(1,2,3,4,5), 1) 
#> [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379
my_log_trans(invec=c(1,2,3,4,5), multiplier=1)
#> [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379
my_log_trans(multiplier=1, invec=c(1,2,3,4,5))
#> [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379

Created on 2020-01-11 by the reprex package (v0.3.0)

2 Likes

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.