R中的加权欧氏距离
Weighted Euclidean Distance in R
我想用数据框的加权欧几里得距离创建一个距离矩阵。权重将在向量中定义。这是一个例子:
library("cluster")
a <- c(1,2,3,4,5)
b <- c(5,4,3,2,1)
c <- c(5,4,1,2,3)
df <- data.frame(a,b,c)
weighting <- c(1, 2, 3)
dm <- as.matrix(daisy(df, metric = "euclidean", weights = weighting))
我到处搜索,但在 R 中找不到相关的包或解决方案。'cluster' 包中的 'daisy' 函数声称支持加权,但权重不支持似乎被应用了,它只是吐出普通的欧几里德。距离。
堆栈溢出有什么想法吗?
我们可以使用@WalterTross 的缩放技术,首先将每一列乘以其各自权重的平方根:
newdf <- sweep(df, 2, weighting, function(x,y) x * sqrt(y))
as.matrix(daisy(newdf, metric="euclidean"))
但以防万一您希望更好地控制和了解什么是欧氏距离,我们可以编写一个自定义函数。请注意,我选择了不同的加权方法。 :
xpand <- function(d) do.call("expand.grid", rep(list(1:nrow(d)), 2))
euc_norm <- function(x) sqrt(sum(x^2))
euc_dist <- function(mat, weights=1) {
iter <- xpand(mat)
vec <- mapply(function(i,j) euc_norm(weights*(mat[i,] - mat[j,])),
iter[,1], iter[,2])
matrix(vec,nrow(mat), nrow(mat))
}
我们可以通过检查 daisy
函数来测试结果:
#test1
as.matrix(daisy(df, metric="euclidean"))
# 1 2 3 4 5
# 1 0.000000 1.732051 4.898979 5.196152 6.000000
# 2 1.732051 0.000000 3.316625 3.464102 4.358899
# 3 4.898979 3.316625 0.000000 1.732051 3.464102
# 4 5.196152 3.464102 1.732051 0.000000 1.732051
# 5 6.000000 4.358899 3.464102 1.732051 0.000000
euc_dist(df)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0.000000 1.732051 4.898979 5.196152 6.000000
# [2,] 1.732051 0.000000 3.316625 3.464102 4.358899
# [3,] 4.898979 3.316625 0.000000 1.732051 3.464102
# [4,] 5.196152 3.464102 1.732051 0.000000 1.732051
# [5,] 6.000000 4.358899 3.464102 1.732051 0.000000
我之所以怀疑沃尔特的方法是因为首先,我从未见过用平方根来计算权重,通常是 1/w
。其次,当我将您的权重应用于我的函数时,我得到了不同的结果。
euc_dist(df, weights=weighting)
我想用数据框的加权欧几里得距离创建一个距离矩阵。权重将在向量中定义。这是一个例子:
library("cluster")
a <- c(1,2,3,4,5)
b <- c(5,4,3,2,1)
c <- c(5,4,1,2,3)
df <- data.frame(a,b,c)
weighting <- c(1, 2, 3)
dm <- as.matrix(daisy(df, metric = "euclidean", weights = weighting))
我到处搜索,但在 R 中找不到相关的包或解决方案。'cluster' 包中的 'daisy' 函数声称支持加权,但权重不支持似乎被应用了,它只是吐出普通的欧几里德。距离。
堆栈溢出有什么想法吗?
我们可以使用@WalterTross 的缩放技术,首先将每一列乘以其各自权重的平方根:
newdf <- sweep(df, 2, weighting, function(x,y) x * sqrt(y))
as.matrix(daisy(newdf, metric="euclidean"))
但以防万一您希望更好地控制和了解什么是欧氏距离,我们可以编写一个自定义函数。请注意,我选择了不同的加权方法。 :
xpand <- function(d) do.call("expand.grid", rep(list(1:nrow(d)), 2))
euc_norm <- function(x) sqrt(sum(x^2))
euc_dist <- function(mat, weights=1) {
iter <- xpand(mat)
vec <- mapply(function(i,j) euc_norm(weights*(mat[i,] - mat[j,])),
iter[,1], iter[,2])
matrix(vec,nrow(mat), nrow(mat))
}
我们可以通过检查 daisy
函数来测试结果:
#test1
as.matrix(daisy(df, metric="euclidean"))
# 1 2 3 4 5
# 1 0.000000 1.732051 4.898979 5.196152 6.000000
# 2 1.732051 0.000000 3.316625 3.464102 4.358899
# 3 4.898979 3.316625 0.000000 1.732051 3.464102
# 4 5.196152 3.464102 1.732051 0.000000 1.732051
# 5 6.000000 4.358899 3.464102 1.732051 0.000000
euc_dist(df)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0.000000 1.732051 4.898979 5.196152 6.000000
# [2,] 1.732051 0.000000 3.316625 3.464102 4.358899
# [3,] 4.898979 3.316625 0.000000 1.732051 3.464102
# [4,] 5.196152 3.464102 1.732051 0.000000 1.732051
# [5,] 6.000000 4.358899 3.464102 1.732051 0.000000
我之所以怀疑沃尔特的方法是因为首先,我从未见过用平方根来计算权重,通常是 1/w
。其次,当我将您的权重应用于我的函数时,我得到了不同的结果。
euc_dist(df, weights=weighting)