这是我将如何编写它,outer
用作双循环的替代品。请注意,它仍然进行了比需要更多的计算,但肯定更快。我假设conn
是一个方阵。
原代码:
f1 <- function(conn) {
for (i in 2:dim(conn)[1]) {
for (j in 2:dim(conn)[1]) {
if ((conn[i, 1] == conn[1, j]) & conn[i, 1] != 0) {
conn[i, j] <- 1
conn[j, i] <- 1
} else {
conn[i, j] <- 0
conn[j, i] <- 0
}
}
}
return(conn)
}
我的建议:
f2 <- function(conn) {
matches <- 1*outer(conn[-1,1], conn[1,-1], `==`)
matches[conn[-1,1] == 0, ] <- 0
ind <- upper.tri(matches)
matches[ind] <- t(matches)[ind]
conn[-1,-1] <- matches
return(conn)
}
一些样本数据:
set.seed(12345678)
conn <- matrix(sample(1:2, 5*5, replace=TRUE), 5, 5)
conn
# [,1] [,2] [,3] [,4] [,5]
# [1,] 2 2 1 2 1
# [2,] 1 1 2 2 1
# [3,] 2 2 1 2 1
# [4,] 2 2 2 2 1
# [5,] 1 1 2 2 1
结果:
f1(conn)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 2 2 1 2 1
# [2,] 1 0 1 1 0
# [3,] 2 1 0 0 1
# [4,] 2 1 0 1 0
# [5,] 1 0 1 0 1
identical(f1(conn), f2(conn))
# [1] TRUE
一个更大的例子,时间比较:
set.seed(12345678)
conn <- matrix(sample(1:2, 1000*1000, replace=TRUE), 1000, 1000)
system.time(a1 <- f1(conn))
# user system elapsed
# 59.840 0.000 57.094
system.time(a2 <- f2(conn))
# user system elapsed
# 0.844 0.000 0.950
identical(a1, a2)
# [1] TRUE
也许不是你能得到的最快的方法(我相信这里的其他人可以使用例如编译器或 Rcpp 找到更快的方法),但我希望对你来说足够短和快。
编辑:由于已经指出(从该代码的提取位置的上下文中)这conn
是一个对称矩阵,我的解决方案可以缩短一点:
f2 <- function(conn) {
matches <- outer(conn[-1,1], conn[1,-1],
function(i,j)ifelse(i==0, FALSE, i==j))
conn[-1,-1] <- as.numeric(matches)
return(conn)
}