关于r:如何使用除欧几里德距离以外的其他距离公式以k表示

how to use different distance formula other than euclidean distance in k means

我正在处理纬度经度数据。我必须根据两点之间的距离进行聚类。现在两个不同点之间的距离是=ACOS(SIN(lat1)*SIN(lat2)+COS(lat1)*COS(lat2)*COS(lon2-lon1))*6371

我想在R中使用k均值。在此过程中,有什么方法可以覆盖距离计算?


K均值不是基于距离的

它基于方差最小化。方差之和公式等于欧几里德距离的平方和,但对于其他距离,反之则不成立。

如果您想对其他距离使用类似k均值的算法(均值不是适当的估计量),请使用k-medoids(PAM)。与k-means相比,k-medoids将与任意距离函数收敛!

对于曼哈顿距离,您还可以使用K中值。中位数是L1范数的适当估计量(中位数使差异之和最小;均值使平方和之差最小)。

对于您的特定用例,您还可以将数据转换为3D空间,然后使用(平方)欧几里得距离,从而使用k-均值。但是您的群集中心将位于地下!


使用以下函数来计算地球距离,不需要现有的R函数。我在Stackoverflow上发现了此功能,只是不记得这篇文章的链接。但是,我已经通过GPS累积距离计算对其进行了验证,并且它可以对齐。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
earthDist <- function (lon1, lat1, lon2, lat2){
  rad <- pi/180
  a1 <- lat1 * rad
  a2 <- lon1 * rad
  b1 <- lat2 * rad
  b2 <- lon2 * rad
  dlon <- b2 - a2
  dlat <- b1 - a1
  a <- (sin(dlat/2))^2 + cos(a1) * cos(b1) * (sin(dlon/2))^2
  c <- 2 * atan2(sqrt(a), sqrt(1 - a))
  R <- 6378.145
  d <- R * c
  return(d)
}

使用以下函数调用该函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
CalculateCumaltiveDist <- function(x,y,id) {

    # #Initiate a vectro P
    km <- vector()
    # #Starting Value is 0, because its home
    km[1] <- 0

    #Loop through the earthly distance function between the first and Nth Row
    for(i in 2:NROW(df)){


      t <-  earthDist(  x[i-1], y[i-1] ,x[i], y[i])
      km[i] <- t

      if( i == 2 ) {

       tmp_All <- data.frame(id[i],x[i], y[i],km[i])

              } else if(i > 2) {

        tmp_All <- rbind(tmp_All, data.frame(id[i],x[i], y[i],km[i]))

        }

    }


    return(sum(tmp_All$km.i., na.rm = T))
}

如果要使用数据框,请删除最终的返回和函数。

这将允许您计算数据框中每个obs-1和obs之间的距离。

如果要成对计算距离,请使用地球距离函数并在obs [1]:[200000]和obs [1:200000]之间循环,直到计算出所有成对组合。然后将此数据转置为矩阵,您应该有一个距离矩阵。

希望这能回答您的问题


如果您有一个数据框df,其中包含latlong的列,那么您应该能够使用fossil包中的earth.dist(...)函数来计算距离矩阵,并将其传递给cluster包中的pam(...)进行聚类。

1
2
3
4
5
library(fossil)
library(cluster)
df    <- data.frame(long=<longituces>, lat=<latitudes>))
dist  <- earth.dist(df, dist=T)
clust <- pam(dist, k, diss=T)

有关文档,请参见earth.dist(...)和pam(...)。