样品的替代品
Alternative for sample
我有以下 sample
使用 sapply
的代码,需要很长时间才能处理(因为执行了很多次):
samples = sapply(rowIndices, function(idx){
sample(vectorToDrawFrom, 1, TRUE, weights[idx, ])
})
问题是我必须根据 rowIndices
中的索引从矩阵中的权重中提取。
有人有更好的想法从矩阵的行中提取吗?
可重现的例子:
rowIndices = floor(runif(1000, 1, 100))
vectorToDrawFrom = runif(5000, 0.0, 2.0)
weights = matrix(runif(100 * 5000, 1, 10), nrow = 100, ncol = 5000)
timer = 0
for (i in 1:2500){
ptm = proc.time()
samples = sapply(rowIndices, function(idx){
sample(vectorToDrawFrom, 1, TRUE, weights[idx, ])
})
timer = timer + (proc.time() - ptm)[3]
}
print(timer) # too long!!
所以这是我可以加速您的代码的方法。需要注意的一件事:采样值不会 "match" 与 rowIndices
尽管按正确的顺序获取事物是微不足道的。 2) 你只存储最后一次迭代,虽然这可能只是因为这是一个最小可重现的例子......
基本上每个 rowIndices
的值只需要调用 sample
一次,因为 rowIndices
的范围是 1-99,即调用 99 次而不是 1000 次,这提供了巨大的速度向上。
我们可以在开始之前对行索引进行排序
rowIndices <- sort(rowIndices) ##sort the row indices and then loop
for (i in 1:15){
samples = unlist(sapply(unique(rowIndices),
function(idx){
sample(vectorToDrawFrom, sum(rowIndices %in% idx),
TRUE, weights[idx, ])
}))
}
Unit: milliseconds
expr
min lq mean median uq max neval cld
newForLoop 263.5668 266.6329 292.8301 268.8920 275.3378 515.899 100 a
OriginalForLoop 698.2982 705.6911 792.2846 712.9985 887.9447 1263.779 100 b
编辑
保持原始向量排序的方法是保存索引或原始rowIndices
向量。然后对行索引进行排序并继续。
set.seed(8675309)
weights = matrix(c(1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0),
nrow = 5, ncol = 3, byrow = T)
rowIndices = c(2,1,2,4)
vectorToDrawFrom = runif(3, 0.0, 2.0)
set.seed(8675309)
##This is the origal code
sample2 = sapply(rowIndices, function(idx){
sample(vectorToDrawFrom, 1, TRUE, weights[idx, ])
})
rowIndx <- order(rowIndices) #get ordering index
rowIndices <- sort(rowIndices)
set.seed(8675309)
samples = unlist(sapply(unique(rowIndices), function(idx){
sample(vectorToDrawFrom, sum(rowIndices %in% idx), TRUE, weights[idx, ])
}))
samples = samples[order(rowIndx)]
all(samples == sample2)
#[1] TRUE
我有以下 sample
使用 sapply
的代码,需要很长时间才能处理(因为执行了很多次):
samples = sapply(rowIndices, function(idx){
sample(vectorToDrawFrom, 1, TRUE, weights[idx, ])
})
问题是我必须根据 rowIndices
中的索引从矩阵中的权重中提取。
有人有更好的想法从矩阵的行中提取吗?
可重现的例子:
rowIndices = floor(runif(1000, 1, 100))
vectorToDrawFrom = runif(5000, 0.0, 2.0)
weights = matrix(runif(100 * 5000, 1, 10), nrow = 100, ncol = 5000)
timer = 0
for (i in 1:2500){
ptm = proc.time()
samples = sapply(rowIndices, function(idx){
sample(vectorToDrawFrom, 1, TRUE, weights[idx, ])
})
timer = timer + (proc.time() - ptm)[3]
}
print(timer) # too long!!
所以这是我可以加速您的代码的方法。需要注意的一件事:采样值不会 "match" 与 rowIndices
尽管按正确的顺序获取事物是微不足道的。 2) 你只存储最后一次迭代,虽然这可能只是因为这是一个最小可重现的例子......
基本上每个 rowIndices
的值只需要调用 sample
一次,因为 rowIndices
的范围是 1-99,即调用 99 次而不是 1000 次,这提供了巨大的速度向上。
我们可以在开始之前对行索引进行排序
rowIndices <- sort(rowIndices) ##sort the row indices and then loop
for (i in 1:15){
samples = unlist(sapply(unique(rowIndices),
function(idx){
sample(vectorToDrawFrom, sum(rowIndices %in% idx),
TRUE, weights[idx, ])
}))
}
Unit: milliseconds
expr
min lq mean median uq max neval cld
newForLoop 263.5668 266.6329 292.8301 268.8920 275.3378 515.899 100 a
OriginalForLoop 698.2982 705.6911 792.2846 712.9985 887.9447 1263.779 100 b
编辑
保持原始向量排序的方法是保存索引或原始rowIndices
向量。然后对行索引进行排序并继续。
set.seed(8675309)
weights = matrix(c(1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0),
nrow = 5, ncol = 3, byrow = T)
rowIndices = c(2,1,2,4)
vectorToDrawFrom = runif(3, 0.0, 2.0)
set.seed(8675309)
##This is the origal code
sample2 = sapply(rowIndices, function(idx){
sample(vectorToDrawFrom, 1, TRUE, weights[idx, ])
})
rowIndx <- order(rowIndices) #get ordering index
rowIndices <- sort(rowIndices)
set.seed(8675309)
samples = unlist(sapply(unique(rowIndices), function(idx){
sample(vectorToDrawFrom, sum(rowIndices %in% idx), TRUE, weights[idx, ])
}))
samples = samples[order(rowIndx)]
all(samples == sample2)
#[1] TRUE