Reputation: 31
I have the following function:
g.Bn = function(n) {
Bn = 0
for(k in 0:n) {
res.of.loop = 0
for(j in 0:k) {
res.of.loop = res.of.loop + (-1)^j * (j + 1)^n * choose(k, j)
}
Bn = res.of.loop * 1/(k+1) + Bn
}
return(Bn)
}
Is here a way to vectorize it instead of using for loops?
Upvotes: 3
Views: 656
Reputation: 1602
You could vectorise the inner loop (as per @DaveT), and use sapply:
g.Bn2 = function(n) {
sum(sapply(0:n, function(k) {
sum((-1)^(0:k) * (0:k + 1)^n * choose(k, 0:k)) * 1/(k+1)
}))
}
Or another possibility to vectorise the outer loop:
g.Bn3 = function(n) {
f <- function(k, n) sum((-1)^(0:k) * (0:k + 1)^n * choose(k, 0:k)) * 1/(k+1)
sum(Vectorize(f, vectorize.args = "k")(0:n, n))
}
> microbenchmark(g.Bn(100), g.Bn2(100), g.Bn3(100))
expr min lq mean median uq max neval
g.Bn(100) 1493.086 1533.9280 1841.3455 1585.354 1675.3575 9023.316 100
g.Bn2(100) 617.063 650.7850 905.6899 738.230 788.7305 9224.460 100
g.Bn3(100) 685.094 772.3785 1015.9182 816.945 860.1775 8213.777 100
Upvotes: 4
Reputation: 6116
You can convert for-loop
to map
and reduce
instead.
In the example below purrr::map
iterate all data, and sum
reduces a numeric vector into a scaler(a numeric vector with length of one).
g.Bn = function(n) {
sum(
purrr::map_dbl(0:n,function(k){
sum(
purrr::map_dbl(0:k,function(j){
(-1)^j * (j + 1)^n * choose(k, j)
})
) * 1/(k+1)
})
)
}
And it seems like all j
s in inner loop can be replaced with 0:k
g.Bn = function(n) {
sum(
purrr::map_dbl(0:n,function(k){
sum((-1)^(0:k) * (0:k + 1)^n * choose(k, 0:k)) * 1/(k+1)
})
)
}
Upvotes: 0