簡體   English   中英

用 mapply 向量化 function

[英]Vectorizing a function with mapply

我在 R 中有一個 function,它采用表示商業折扣結構的字符串並將它們轉換為數字乘數。 例如,字符串“50/20/15”僅表示原價優惠 50%,然后再優惠 20%,然后再優惠 15%。 這相當於將原始價格乘以 (1 - 0.50)*(1 - 0.20)(1 - 0.15),等於 0.34。

我的function如下。

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 function 的各種應用程序,但沒有成功。

如何修改我的 function 以用於字符串向量? 預期的 output 是字符串向量的分量值的數值向量。

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中執行此sapply

> 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 ,然后使用rowProds中的matrixStats

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 

或者創建一個新的 function 名稱然后調用它:

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 

或如圖所示重寫 function。 請注意,strsplit 在此 function 中創建了一個元素列表,並且 [[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 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM