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)