Мы можем использовать 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