如果要计算两个向量的n维距离,可以使用以下函数:
a = c(1:10)
b = seq(20, 23, length.out = length(a))
test_fun =
function(x,y) {
return(
sqrt(
sum(
(x - y) ^ 2
)
)
)
}
n_distance = test_fun(a,b)
现在,我想将其扩展为矩阵设置:我想为两个矩阵的每一对行计算n维距离。
set.seed(123)
a_mtx = matrix(1:30, ncol = 5)
b_mtx = matrix(sample(1:15,15), ncol = 5)
n_distance_mtx =
matrix(
NA,
nrow = nrow(b_mtx),
ncol = nrow(a_mtx)
)
for(i in 1:nrow(b_mtx)) {
for(j in 1:nrow(a_mtx)) {
n_distance_mtx[i,j] =
test_fun(a_mtx[j,], b_mtx[i,])
}
}
n_distance_mtx
的每一列都包含a_mtx
和b_mtx
每行之间的距离度量(因此n_distance_mtx[,1]
是a_mtx[1,]
和{{ 1}}。
如果我计算b_mtx[1:3,]
上的列均值,我可以获得n_distance_mtx
中的每一行与a_mtx
的所有行之间的平均距离。
b_mtx
所以 23.79094 是colMeans(n_distance_mtx)
#[1] 23.79094 24.90281 26.15618 27.53303 29.01668 30.59220
和a_mtx[1,]
之间的平均距离,而 24.90281 是b_mtx[1:3,]
和{ {1}},依此类推。
问题:如何在不使用for循环的情况下达到相同的解决方案?
我想将此方法应用于具有更大维度(约数十万行)的矩阵。从this和this看,似乎必须有一种通过a_mtx[2,]
d b_mtx[1:3,]
函数来完成此任务的方法,但是我一直无法生成这样的函数。
Vectorize
答案 0 :(得分:2)
我们可以将Vectorize
与outer
一起使用
f1 <- Vectorize(function(i, j) test_fun(a_mtx[j, ], b_mtx[i, ]))
out <- outer(seq_len(nrow(b_mtx)), seq_len(nrow(a_mtx)), FUN = f1)
out
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 20.88061 21.84033 22.97825 24.26932 25.69047 27.22132
#[2,] 24.87971 25.57342 26.43861 27.45906 28.61818 29.89983
#[3,] 25.61250 27.29469 29.05168 30.87070 32.74141 34.65545
colMeans(out)
#[1] 23.79094 24.90281 26.15618 27.53303 29.01668 30.59220
identical(n_distance_mtx, out)
#[1] TRUE
答案 1 :(得分:1)
如果我正确地理解了您的问题,则您希望a_mtx
中每个向量(行)与b_mtx
中其他向量之间的欧几里得距离。
如果是这样,您可以像这样使用两次apply:
result = apply(a_mtx, 1, function(x){ apply(b_mtx, 1, function(y){ test_fun(x,y) })})
这给出一个距离矩阵:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 20.88061 21.84033 22.97825 24.26932 25.69047 27.22132
[2,] 24.87971 25.57342 26.43861 27.45906 28.61818 29.89983
[3,] 25.61250 27.29469 29.05168 30.87070 32.74141 34.65545
其中行索引是b_mtx
的对应矢量(行),列索引是a_mtx
的对应矢量
最后,使用以下方法获取平均距离:
colMeans(result)
[1] 23.79094 24.90281 26.15618 27.53303 29.01668 30.59220