r-使用mapply对函数进行矢量化



我在R中有一个函数,它接受表示商业折扣结构的字符串,并将其转换为数字乘数。例如,字符串";50/20/15";这意味着原价可以享受50%的折扣,然后再享受20%的折扣,再享受15%的折扣。这相当于原价乘以(1-0.50(*(1-0.20((1-0.15(,等于0.34。

我的功能如下。

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

其根据需要在单个字符串上工作。

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

不幸的是,这对于字符串向量来说失败了。

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

我尝试过Vectorize函数的各种应用程序,但都没有成功。

如何修改函数以适用于字符串向量?预期输出是字符串向量的分量值的数字向量。

prod也应在循环内

sapply(strsplit(discount_vec, "/"), (x) prod(1 - as.numeric(x)/100))
[1] 0.4500 0.4050 0.3825 0.3600

对于单个元素,mapply使用SIMPLIFY = TRUE,因此我们没有任何问题,但是对于多个元素,它返回list,因此最后一步不起作用

> list(c(1, 3), c(2, 4))/100
Error in list(c(1, 3), c(2, 4))/100 : 
non-numeric argument to binary operator

如果我们使用OP的代码,那么用另一个mapply包装(或者可以在与sapply相同的mapply中这样做(

> disc_str_to_num <- function(string){
+   numstrings <- strsplit(string,"/")
+   nums <- mapply(as.numeric, numstrings)
+   mapply((x) prod(1 - x/100), nums)
+ }
> 
> disc_str_to_num(discount_vec)
[1] 0.4500 0.4050 0.3825 0.3600

另一个选项是用read.table读取为data.frame,然后使用matrixStats中的rowProds

library(matrixStats)
rowProds(as.matrix(1- read.table(text = discount_vec,
header = FALSE, sep = "/", fill = TRUE)/100), na.rm = TRUE)
[1] 0.4500 0.4050 0.3825 0.3600

像这样使用矢量化:

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 

或者创建一个新的函数名,然后调用它:

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 

或者如图所示重写函数。请注意,strsplit在此函数中创建一个单元素列表,并且[[1]]获取内容。

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 

最新更新