試圖避免使用在下面的代碼for
循環利用sapply
循環,如果在所有可能的。循環解決方案對我來說工作得很好,我只是想學習更多的R並儘可能多地探索。試圖避免與sapply(對於GSUB)
目標:有一個載體i
和兩個載體sf
(搜索)和rp
(替換)。對於每個i
需要循環過sf
並用rp
代替哪裏匹配。
i = c("1 6 5 4","7 4 3 1")
sf = c("1","2","3")
rp = c("one","two","three")
funn <- function(i) {
for (j in seq_along(sf)) i = gsub(sf[j],rp[j],i,fixed=T)
return(i)
}
print(funn(i))
結果(正確):
[1] "one 6 5 4" "7 4 three one"
我想要做的非常相同,但sapply
#Trying to avoid a for loop in a fun
#funn1 <- function(i) {
# i = gsub(sf,rp,i,fixed=T)
# return(i)
#}
#print(sapply(i,funn1))
顯然,上面的註釋代碼不會爲我的工作只能得到sf
的第一個元素。這是我第一次使用sapply
,所以我不確定如何將「內部」隱式循環轉換爲矢量化解決方案。任何幫助(即使是一個聲明 - 這是不可能的)表示讚賞!
(我知道的mgsub
但在這裏,這是解決不了問題想保持gsub
。)
編輯:該包裝完整的代碼和belowoffered解決方案和時間安排:
#timing
library(microbenchmark)
library(functional)
i = rep(c("1 6 5 4","7 4 3 1"),10000)
sf = rep(c("1","2","3"),100)
rp = rep(c("one","two","three"),100)
#Loop
funn <- function(i) {
for (j in seq_along(sf)) i = gsub(sf[j],rp[j],i,fixed=T)
return(i)
}
t1 = proc.time()
k = funn(i)
t2 = proc.time()
#print(k)
print(microbenchmark(funn(i),times=10))
#mapply
t3 = proc.time()
mapply(function(u,v) i<<-gsub(u,v,i), sf, rp)
t4 = proc.time()
#print(i)
print(microbenchmark(mapply(function(u,v) i<<-gsub(u,v,i), sf, rp),times=10))
#Curry
t5 = proc.time()
Reduce(Compose, Map(function(u,v) Curry(gsub, pattern=u, replacement=v), sf, rp))(i)
t6 = proc.time()
print(microbenchmark(Reduce(Compose, Map(function(u,v) Curry(gsub, pattern=u, replacement=v), sf, rp))(i), times=10))
#4th option
n <- length(sf)
sf <- setNames(sf,1:n)
rp <- setNames(rp,1:n)
t7 = proc.time()
Reduce(function(x,j) gsub(sf[j],rp[j],x,fixed=TRUE),c(list(i),as.list(1:n)))
t8 = proc.time()
print(microbenchmark(Reduce(function(x,j) gsub(sf[j],rp[j],x,fixed=TRUE),c(list(i),as.list(1:n))),times=10))
#Usual proc.time
print(t2-t1)
print(t4-t3)
print(t6-t5)
print(t8-t7)
時報:
Unit: milliseconds
expr min lq mean median uq max neval
funn(i) 143 143 149 145 147 165 10
Unit: seconds
expr min lq mean median uq max neval
mapply(function(u, v) i <<- gsub(u, v, i), sf, rp) 4.1 4.2 4.4 4.3 4.4 4.9 10
Unit: seconds
expr min lq mean median uq max neval
Reduce(Compose, Map(function(u, v) Curry(gsub, pattern = u, replacement = v), sf, rp))(i) 1.6 1.6 1.7 1.7 1.7 1.7 10
Unit: milliseconds
expr min lq mean median uq max neval
Reduce(function(x, j) gsub(sf[j], rp[j], x, fixed = TRUE), c(list(i), as.list(1:n))) 141 144 147 145 146 162 10
user system elapsed
0.15 0.00 0.15
user system elapsed
4.49 0.03 4.52
user system elapsed
1.68 0.02 1.68
user system elapsed
0.19 0.00 0.18
所以,確實是在這種情況下,for
循環提供了最佳時機,是(在我看來)最straightforwar d,簡單,可能優雅。堅持循環。
感謝所有。所有建議都被接受並提升。
通常,您在同時測試的所有東西上使用'microbenchmark'。另外,如果再次擔心這一問題,您可能希望在未來的問題上使用「效果」標籤。順便說一下,盛林的答案實際上是使用'sapply'。 – Frank
我的目標是估計每個解決方案分別運行多久,以防備用解決方案比循環快得多。 upvoted盛林的回答也是 –