尝试使用
目标:有一个向量
显然,上述代码不起作用,因为我只能获取
(我知道
编辑:完整的代码与包和下面提供的解决方案和时间:
因此,在这种情况下,
谢谢大家。所有建议都被接受并赞同。
sapply
来避免在以下代码中使用for
循环,如果可能的话。对于我来说,循环解决方案完全正常,我只是想学习更多R并尽可能探索许多方法。目标:有一个向量
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
)编辑:完整的代码与包和下面提供的解决方案和时间:
#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
循环提供了最佳的时间,并且(在我看来)最直接、简单和可能优雅。坚持使用循环。谢谢大家。所有建议都被接受并赞同。
microbenchmark
。此外,如果性能再次成为问题,您可能希望在未来的问题中标记为performance
。顺便说一句,Shenglin的答案实际上确实使用了sapply
。 - Frank