我们可以使用expand.grid创建所有索引组合,然后使用map2_dbl循环遍历所有组合,最后创建一个矩阵。
library(purrr)
ind <- expand.grid(1:NRows, 1:NRows)
norm <- matrix(map2_dbl(ind$Var1, ind$Var2, ~sum((myMat[.x,] - myMat[.y,])^2)),
NRows, NCols)
norm
# [,1] [,2] [,3] [,4]
# [1,] 0.0000000 0.7408859 0.9713548 0.9768185
# [2,] 0.7408859 0.0000000 0.8285694 0.1746331
# [3,] 0.9713548 0.8285694 0.0000000 0.3690422
# [4,] 0.9768185 0.1746331 0.3690422 0.0000000
类似的想法,但我们也可以使用Vectorize。
myfun <- function(x, y) sum((myMat[x,] - myMat[y,])^2)
myfun_v <- Vectorize(myfun)
norm <- matrix(myfun_v(ind$Var1, ind$Var2), NRows, NCols)
norm
# [,1] [,2] [,3] [,4]
# [1,] 0.0000000 0.7408859 0.9713548 0.9768185
# [2,] 0.7408859 0.0000000 0.8285694 0.1746331
# [3,] 0.9713548 0.8285694 0.0000000 0.3690422
# [4,] 0.9768185 0.1746331 0.3690422 0.0000000
这是当前方法的速度比较,包括另一个答案中的 dist 函数。
library(microbenchmark)
microbenchmark(m1 = {ind <- expand.grid(1:NRows, 1:NRows);
matrix(map2_dbl(ind$Var1, ind$Var2, ~sum((myMat[.x,] - myMat[.y,])^2)),
NRows,NCols)},
m2 = {ind <- expand.grid(1:NRows, 1:NRows);
myfun <- function(x, y) sum((myMat[x,] - myMat[y,])^2);
myfun_v <- Vectorize(myfun);
matrix(myfun_v(ind$Var1, ind$Var2), NRows, NCols)},
m3 = {for (i in 1:nrow(myMat)){
for (j in 1:nrow(myMat)){
norm <- matrix(0, NRows, NCols);
norm[i,j] <- sum((myMat[i,]-myMat[j,])^2)
}}},
m4 = {dist(myMat, diag = TRUE, upper = TRUE)^2}
)
Unit: microseconds
expr min lq mean median uq max neval cld
m1 261.142 278.3625 310.1212 302.5230 323.8570 434.894 100 b
m2 200.997 238.7805 287.5953 259.5995 286.3305 2417.610 100 b
m3 4902.562 5369.8390 5725.5358 5578.2895 5717.8560 10317.123 100 c
m4 16.451 22.6200 34.1653 32.9010 42.4110 81.222 100 a