R:如何向量化代码以删除 for 循环
R: how to vectorize code to remove for loop
我正在用 R 编写一个 Monte Carlo 模拟,我需要执行 100,000 次。我遇到了一些效率问题。我遇到的一个关键效率问题是我在较大的 Monte Carlo for 循环内有一个 for 循环。如果可能的话,我想尝试删除这个循环,但目前很难过。
我有一个数据框,其中包含一个值以及一个开始和结束,它们是最终矩阵的索引。
这是一个示例代码片段:
a <- data.frame( value = c( 3, 10, 5, 8),
start = c(2, 3, 4, 5),
end = c( 9, 10, 9, 8 ))
b <- matrix( 0, nrow = nrow(a), ncol = 10)
# this is the for loop that I would like to remove
for ( i in 1:nrow(a) ) {
b[ i, a$start[i]:a$end[i] ]<- a$value[i]
}
感觉好像我应该能够将问题重新定义为某种类型的连接,但我一直未能取得进展。感谢任何帮助。
矢量化 rep.int
、sequence
和矩阵索引:
len <- a$end - a$start + 1
b[matrix(c(rep.int(1:nrow(a), len), sequence(len, a$start)), ncol = 2)] <- rep.int(a$value, len)
在更大的数据集上,向量化版本的速度提高了 > 13 倍:
a <- data.frame(value = sample(10, 1e5, replace = TRUE),
start = sample(5, 1e5, replace = TRUE),
end = sample(6:10, 1e5, replace = TRUE))
b <- matrix(0, nrow = nrow(a), ncol = 10)
vecfill <- function(a, b) {
len <- a$end - a$start + 1
b[matrix(c(rep.int(1:nrow(a), len), sequence(len, a$start)), ncol = 2)] <- rep.int(a$value, len)
return(b)
}
iterfill <- function(a, b) {
for ( i in 1:nrow(a) ) {
b[ i, a$start[i]:a$end[i] ]<- a$value[i]
}
return(b)
}
microbenchmark::microbenchmark(vecfill(a, b), iterfill(a, b), times = 100)
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> vecfill(a, b) 19.5291 19.99705 24.72165 21.01205 24.0373 75.8988 100
#> iterfill(a, b) 292.6082 310.52755 330.09472 319.50020 331.3736 560.9486 100
我正在用 R 编写一个 Monte Carlo 模拟,我需要执行 100,000 次。我遇到了一些效率问题。我遇到的一个关键效率问题是我在较大的 Monte Carlo for 循环内有一个 for 循环。如果可能的话,我想尝试删除这个循环,但目前很难过。
我有一个数据框,其中包含一个值以及一个开始和结束,它们是最终矩阵的索引。
这是一个示例代码片段:
a <- data.frame( value = c( 3, 10, 5, 8),
start = c(2, 3, 4, 5),
end = c( 9, 10, 9, 8 ))
b <- matrix( 0, nrow = nrow(a), ncol = 10)
# this is the for loop that I would like to remove
for ( i in 1:nrow(a) ) {
b[ i, a$start[i]:a$end[i] ]<- a$value[i]
}
感觉好像我应该能够将问题重新定义为某种类型的连接,但我一直未能取得进展。感谢任何帮助。
矢量化 rep.int
、sequence
和矩阵索引:
len <- a$end - a$start + 1
b[matrix(c(rep.int(1:nrow(a), len), sequence(len, a$start)), ncol = 2)] <- rep.int(a$value, len)
在更大的数据集上,向量化版本的速度提高了 > 13 倍:
a <- data.frame(value = sample(10, 1e5, replace = TRUE),
start = sample(5, 1e5, replace = TRUE),
end = sample(6:10, 1e5, replace = TRUE))
b <- matrix(0, nrow = nrow(a), ncol = 10)
vecfill <- function(a, b) {
len <- a$end - a$start + 1
b[matrix(c(rep.int(1:nrow(a), len), sequence(len, a$start)), ncol = 2)] <- rep.int(a$value, len)
return(b)
}
iterfill <- function(a, b) {
for ( i in 1:nrow(a) ) {
b[ i, a$start[i]:a$end[i] ]<- a$value[i]
}
return(b)
}
microbenchmark::microbenchmark(vecfill(a, b), iterfill(a, b), times = 100)
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> vecfill(a, b) 19.5291 19.99705 24.72165 21.01205 24.0373 75.8988 100
#> iterfill(a, b) 292.6082 310.52755 330.09472 319.50020 331.3736 560.9486 100