[SOLVED] Vectorizing a function with mapply

Issue

I have a function in R which takes strings which represent commerce discount structures and converts them into numerical multipliers. For example, the string "50/20/15" just means that the original price gets 50% off, then another 20% off, then another 15% off. This will be equivalent to multiplying the original price by (1 – 0.50)*(1 – 0.20)(1 – 0.15), which equals 0.34.

My function is as follows.

disc_str_to_num <- function(string){
  numstrings <- strsplit(string,"/")
  nums <- mapply(as.numeric, numstrings)
  prod(1 - nums/100)
}

which works as desired on single strings.

> disc_str_to_num("50/20/15")
[1] 0.34

Unfortunately this fails for string vectors.

discount_vec <- c("50/10",
                  "50/10/10",
                  "50/10/15",
                  "50/10/20")

> disc_str_to_num(discount_vec)
Error in nums/100 : non-numeric argument to binary operator

I have tried various applications of the Vectorize function, with no success.

How may I modify my function to work for string vectors? The expected output is a numeric vector of the component-wise values of the string vector.

Solution

Use Vectorize like this:

Vectorize(disc_str_to_num)(discount_vec)
##    50/10 50/10/10 50/10/15 50/10/20 
##   0.4500   0.4050   0.3825   0.3600 

or create a new function name and then invoke it:

disc_str_to_num_vec <- Vectorize(disc_str_to_num)

disc_str_to_num_vec(discount_vec)
##    50/10 50/10/10 50/10/15 50/10/20 
##   0.4500   0.4050   0.3825   0.3600 

or rewrite the function as shown. Note that strsplit creates a one element list in this function and [[1]] takes the contents.

disc_str_to_num_vec2 <- 
  Vectorize(function(x) prod(1 - as.numeric(strsplit(x, "/")[[1]]) / 100))

disc_str_to_num_vec2(discount_vec)
##    50/10 50/10/10 50/10/15 50/10/20 
##   0.4500   0.4050   0.3825   0.3600 

Answered By – G. Grothendieck

Answer Checked By – Jay B. (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *