我有一个项目,我将有一个大矩阵,我根据周围的单元格随机选择要修改的单元格。在尝试转移到RCpp之前,我试图弄清楚如何尽可能地优化它(或者除此之外)。我还有其他代码来处理矩阵的边缘和诸如此类的东西,但是这个最小的例子可以让你了解我的目标。在这个例子中,我随机选择单元格的原始内容或其中一个邻居来获取原始单元格的值。我提出了三种执行此操作的方法 - pick_random1
适用于apply
,pick_random2
适用于mapply
,而pick_random3
适用于for
{1}}循环。为了使*apply
函数起作用,我需要使用一个全局变量,我知道这个变量并不理想。令人惊讶的是,这些也是最慢的选择。
pick_random1 <- function(row_column){
row <- row_column[1]
column <- row_column[2]
neighbors <- my_mat[(row-1):(row+1), (column-1):(column+1)]
my_mat[row,column] <<- sample(neighbors, 1)
}
pick_random2 <- function(row, column){
neighbors <- my_mat[(row-1):(row+1), (column-1):(column+1)]
my_mat[row,column] <<- sample(neighbors, 1)
}
pick_random3 <- function(row, column, l_matrix){
neighbors <- l_matrix[(row-1):(row+1), (column-1):(column+1)]
sample(neighbors, 1)
}
my_mat <- matrix(1:25, nrow=5)
my_mat
rows <- c(2,3,4)
cols <- c(2,3,4)
benchmark(apply(cbind(rows, cols), 1, pick_random1), replications=100000)$elapsed
#[1] 5.346
benchmark(mapply(pick_random2, rows, cols), replications=100000)$elapsed
#[1] 3.551
benchmark(
for(i in 1:length(rows)){
my_mat[rows[i],cols[i]] <- pick_random3(rows[i], cols[i], l_matrix=my_mat)
}, replications=100000)$elapsed
#[1] 2.419
有关如何在不使用for
循环的情况下进一步加快速度或如何执行此操作的任何建议?我应该补充一点,能够按顺序而不是一次性更新矩阵非常重要。
答案 0 :(得分:1)
我假设你想从初始状态中选择邻居而不是迭代(因为那样你就不能避免循环)。
my_mat <- matrix(1:25, nrow=5)
rows <- c(2,3,4)
cols <- c(2,3,4)
set.seed(42)
#find neighbor
neighbor <- arrayInd(sample(1:9, length(rows), replace = TRUE), c(3L,3L)) - 2
# [,1] [,2]
#[1,] 1 1
#[2,] 1 1
#[3,] 1 -1
#replace
my_mat[cbind(rows, cols)] <- my_mat[cbind(rows, cols) + neighbor]
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 6 11 16 21
#[2,] 2 13 12 17 22
#[3,] 3 8 19 18 23
#[4,] 4 9 14 15 24
#[5,] 5 10 15 20 25
如果你需要迭代,你需要一个循环,仅用于最后一步:
for (i in seq_along(rows))
my_mat[rows[i], cols[i]] <- my_mat[rows[i] + neighbor[i, 1],
cols[i] + neighbor[i, 2]]