gpt4 book ai didi

r - 根据另一个矩阵改进矩阵操作的 for 循环的方法

转载 作者:行者123 更新时间:2023-12-04 12:35:16 25 4
gpt4 key购买 nike

我知道改进 for 循环之前已经被问过很多次了。
我们可以应用族函数来改进 R 中的 for 循环。

但是,有没有办法改进矩阵的操作,其中这些操作依赖于另一个矩阵?我在这里的意思是,我在 test 中将元素设置为 2基于另一个矩阵 index :

for (i in 1:nrow(test)){
test[i,index[i,]] <- 2
} # where index is predetermined matrix

另一个例子是,我在 test 中设置值基于另一个矩阵的行中元素的顺序 anyMatrix :
for (i in 1:nrow(test)){
test[i,] <- order(anyMatrix[i,])
}

我可以在这里使用 lapply 或 sapply 但它们返回一个列表,并且将其转换回矩阵需要相同的时间。

可重现的例子:
test <- matrix(0, nrow = 10, ncol = 10)
set.seed(1234)
index <- matrix(sample.int(10, 10*10, TRUE), 10, 10)
anyMatrix <- matrix(rnorm(10*10), nrow = 10, ncol = 10)

for (i in 1:nrow(test)){
test[i,index[i,]] <- 2
}

for (i in 1:nrow(test)){
test[i,] <- order(anyMatrix[i,])
}

最佳答案

您在这里似乎真的有两个不同的问题。

问题 1 : 给定一个矩阵 index , 每行 i和专栏j您要设置test[i,j]到 2 如果 j出现在 i 行的 index .这可以通过简单的矩阵索引来完成,传递一个 2 列的索引矩阵,其中第一列是要索引的所有元素的行,第二列是要索引的所有元素的列:

test[cbind(as.vector(row(index)), as.vector(index))] <- 2
test
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 2 2 0 2 2 2 2 0 2 2
# [2,] 2 0 2 2 2 2 2 0 2 2
# [3,] 2 2 2 2 0 0 2 2 0 0
# [4,] 2 2 0 0 0 2 2 2 0 2
# [5,] 2 2 2 2 0 0 0 0 2 0
# [6,] 0 0 0 0 0 2 2 2 2 0
# [7,] 2 0 2 2 2 2 2 0 0 0
# [8,] 2 0 2 2 2 2 0 2 0 2
# [9,] 2 2 2 2 0 0 2 0 2 2
# [10,] 2 0 2 0 0 2 2 2 2 0

由于这在单个向量化操作中完成所有操作,因此它应该比循环遍历行并单独处理它们更快。这是一个包含 100 万行和 10 列的示例:
OP <- function(test, index) {
for (i in 1:nrow(test)){
test[i,index[i,]] <- 2
}
test
}
josliber <- function(test, index) {
test[cbind(as.vector(row(index)), as.vector(index))] <- 2
test
}
test.big <- matrix(0, nrow = 1000000, ncol = 10)
set.seed(1234)
index.big <- matrix(sample.int(10, 1000000*10, TRUE), 1000000, 10)
identical(OP(test.big, index.big), josliber(test.big, index.big))
# [1] TRUE
system.time(OP(test.big, index.big))
# user system elapsed
# 1.564 0.014 1.591
system.time(josliber(test.big, index.big))
# user system elapsed
# 0.408 0.034 0.444

在这里,矢量化方法快了 3.5 倍。

问题2 : 您要设置行 itestorder应用于 anyMatrix的对应行.你可以用 apply 来做到这一点:
(test <- t(apply(anyMatrix, 1, order)))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 1 10 7 8 4 5 3 6 2 9
# [2,] 8 7 1 6 3 4 9 5 10 2
# [3,] 4 9 7 1 3 2 6 10 5 8
# [4,] 1 2 6 4 10 3 9 8 7 5
# [5,] 9 6 5 1 2 7 10 4 8 3
# [6,] 9 3 8 6 5 10 1 4 7 2
# [7,] 3 7 2 5 6 8 9 4 1 10
# [8,] 9 8 1 3 4 6 7 10 5 2
# [9,] 8 4 3 6 10 7 9 5 2 1
# [10,] 4 1 9 3 6 7 8 2 10 5

我不希望这里的运行时有太大变化,因为 apply实际上只是循环遍历行,类似于您在解决方案中的循环方式。尽管如此,我还是更喜欢这个解决方案,因为它可以减少打字次数,而且做事方式更“R”。

请注意,这两个应用程序使用了完全不同的代码,这在 R 数据操作中非常典型——有很多不同的专用运算符,您需要选择适合您任务的运算符。我不认为有一个单一的函数,甚至真的是一小组函数能够处理所有矩阵操作,其中该操作基于另一个矩阵的数据。

关于r - 根据另一个矩阵改进矩阵操作的 for 循环的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35242495/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com