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)
}