R中具有测地线或大圆距离的空间测地纬度经度聚类的方法

时间:2014-01-13 15:23:48

标签: r cluster-analysis

我想将一些基本的聚类技术应用于某些纬度和经度坐标。沿着聚类(或一些无监督学习)的方式将坐标分组成由great circle距离或geodesic距离决定的。 注意:这可能是一个非常糟糕的方法,所以请指教。

理想情况下,我想在R中解决此问题。

我做了一些搜索,但也许我错过了一个坚实的方法?我遇到过这些软件包:flexclustpam - 但是,我没有遇到过以下方面明确的例子:

  1. 定义我自己的距离函数。
  2. flexclut(通过kccacclust)或pam是否会考虑随机重启?
  3. 锦上添花=有没有人知道可以指定每个群集中最小元素数量的方法/包?

2 个答案:

答案 0 :(得分:17)

关于你的第一个问题:由于数据是long / lat,一种方法是在earth.dist(...)包中使用fossil(计算大圆圈):

library(fossil)
d = earth.dist(df)    # distance object

另一种方法使用distHaversine(...)包中的geosphere

geo.dist = function(df) {
  require(geosphere)
  d <- function(i,z){         # z[1:2] contain long, lat
    dist <- rep(0,nrow(z))
    dist[i:nrow(z)] <- distHaversine(z[i:nrow(z),1:2],z[i,1:2])
    return(dist)
  }
  dm <- do.call(cbind,lapply(1:nrow(df),d,df))
  return(as.dist(dm))
}

此处的优点是您可以使用geosphere中的任何其他距离算法,或者您可以定义自己的距离函数并使用它来代替distHaversine(...)。然后应用任何基本R聚类技术(例如,kmeans,hclust):

km <- kmeans(geo.dist(df),centers=3)  # k-means, 3 clusters
hc <- hclust(geo.dist(df))            # hierarchical clustering, dendrogram
clust <- cutree(hc, k=3)              # cut the dendrogram to generate 3 clusters

最后,一个真实的例子:

setwd("<directory with all files...>")
cities <- read.csv("GeoLiteCity-Location.csv",header=T,skip=1)
set.seed(123)
CA     <- cities[cities$country=="US" & cities$region=="CA",]
CA     <- CA[sample(1:nrow(CA),100),]   # 100 random cities in California
df     <- data.frame(long=CA$long, lat=CA$lat, city=CA$city)

d      <- geo.dist(df)   # distance matrix
hc     <- hclust(d)      # hierarchical clustering
plot(hc)                 # dendrogram suggests 4 clusters
df$clust <- cutree(hc,k=4)

library(ggplot2)
library(rgdal)
map.US  <- readOGR(dsn=".", layer="tl_2013_us_state")
map.CA  <- map.US[map.US$NAME=="California",]
map.df  <- fortify(map.CA)
ggplot(map.df)+
  geom_path(aes(x=long, y=lat, group=group))+
  geom_point(data=df, aes(x=long, y=lat, color=factor(clust)), size=4)+
  scale_color_discrete("Cluster")+
  coord_fixed()

城市数据来自GeoLite。美国States shapefile来自Census Bureau

编辑以回应@ Anony-Mousse评论:

“LA”在两个集群之间划分似乎很奇怪,但是,扩展地图显示,对于这个随机选择的城市,集群3和集群4之间存在差距。集群4基本上是圣莫尼卡和伯班克;第3组是帕萨迪纳,南洛杉矶,长滩以及南部的一切。

K-means聚类(4个聚类)确实将LA / Santa Monica / Burbank / Long Beach周围的区域保持在一个聚类中(见下文)。这仅归结为kmeans(...)hclust(...)使用的不同算法。

km <- kmeans(d, centers=4)
df$clust <- km$cluster

值得注意的是,这些方法要求所有点必须进入某个群集。如果您只是询问哪些点靠近在一起,并允许某些城市不进入任何群集,那么您会得到截然不同的结果。

答案 1 :(得分:0)

我偶尔会使用ELKI对空间数据进行聚类。

它不是R(我不喜欢R,并且发现它在很多情况下都非常慢。事实上,除了简单的矩阵乘法和简单调用C或Fortran代码之外的任何事情都很慢。)

无论如何,ELKI支持大地距离,甚至是这些距离的索引加速(通过M树和R *树;大量加载的R *树对我来说效果最好,并产生大量加速) ;许多聚类算法,如DBSCAN和OPTICS,可以与这些距离函数一起使用。

以下是ELKI群集的示例:https://stackoverflow.com/a/14702758/1060350

我没有保留代码。不确定我是否使用Python进行KML输出,或者是否实现了ELKI输出模块。