在R

时间:2016-02-02 14:44:14

标签: r algorithm ggplot2 cluster-analysis

我正在尝试使用R复制类似于以下paper中描述的聚类过程。第7页和第8页详细讨论了聚类过程。我有一系列货物的原点和目的地坐标,我想将货物集中到地理区域。但是,在R中应用k-means过程之前,我不完全确定构建空间数据所需的形式。

我最初的想法是,论文的输入数据看起来像这样:

Olat    Olong    Dlat    Dlong   Dist.Vol

34.271  -86.217  34.838 -81.686  226.6021
30.889  -87.776  30.689 -88.049  400
33.524  -86.805  34.167 -84.789  674.07
33.524  -86.805 34.779  -82.311  1100.66
33.524  -86.805 36.159  -86.791  800
34.201  -86.166 40.019  -82.878  2350
31.158  -88.016 45.524  -122.675 6711.44
.         .       .      .       .       
.         .       .      .       .       
.         .       .      .       .       
31.158  -88.016 32.084  -81.1   1301.85

在这种情况下,在R中执行我的k-means聚类就像下面这样简单:

input <- cbind( data$Olat, data$Olong, data$Dlat, data$Dlong, data$Dist.Vol)
results <- kmeans( data, 20)   # 20 determined optimal in paper

我一直很难看到这个程序的结果。我能够找到的大多数空间k均值聚类示例只包含一组纬度和经度坐标。

我不确定是否或如何在我的群集过程中考虑原始目的地关系。我很感激我能得到任何帮助。谢谢。

修改

我很清楚如何使用Haversine函数计算非欧氏距离。我无法理解这篇文章的确切含义:

  

“使用k-means,每个坐标首先与其在原点和目的地的频率成比例地加权。然后根据预定数量,通过最小化坐标之间的加权距离来形成聚类。”

对于每个不同的起点和终点(纬度,经度)组合,我可以计算它作为目的地和原点出现的频率,然后将其乘以平均出货距离吗?我不确定如何在考虑原点和目的地之间的关系的同时在二维中执行k-means算法。

lat    long        Dist*Vol

34.271  -86.217     226.6021
30.889  -87.776     400
.         .            .
.         .            .
.         .            .
31.158  -88.016     1301.85

2 个答案:

答案 0 :(得分:1)

看起来你基于5种不同的功能集群--Olong,Olat,Dlong,Dlat和Dist.Vol。

如果要创建空间群集,则只需要两个功能。如果我理解正确的话,你应该跟Dlong和Olat和Dlat一起训练Olong。

 data <- data.frame(lat = c(data$Olat,data$Dlat), lon = c(data$Olong,data$Dlong)

然后你可以在这个二维空间上应用k-means。

 results <- kmeans(data, 20)

请注意,使用欧几里德距离(k-means的默认值)不是此处度量的正确选择。您应该使用Haversineproject your points to a Cartesian space

关于可视化 - 一旦你设置了k-means,就可以绘制质心+ Voronoi diagram。看起来这是本文的情况。有关详细信息,请参阅this question

答案 1 :(得分:1)

更新

通过决定只关注大量出货货物区域,我有点简化了我的问题。现在,我的输入数据带有一些5,000个不同的城市,并附有平均统计数据CPM =每英里成本和Volume =出境货件数量。

Oid    Long      Lat    CPM    Volume
203   -85.251   31.579  1.661   97
 .      .         .       .     .

我想根据地理距离以及每英里的平均出站费用进行群集。为了考虑到卷I,我根据货件数量Oid在我的输入矩阵中复制了每个Volume(原始城市)。为此,我使用了以下代码:

Distinct.Origins <- read.csv(".... file path... ")

by_origin <- group_by(Distinct.Origins, Oid)
o.expand  <- by_origin[rep(seq(nrow(by_origin)), by_origin$Volume), 1:9]  # 9 columns in data.frame

input <- as.data.frame(cbind(o.expand$Olong, o.expand$Olat, o.expand$CPM))
colnames(input) <- c("long", "lat", "CPM")

# To get a sense of what this looks like Oid = 203 now has 97 rows

head(input)
     long    lat      CPM
 -85.251 31.579 1.661815
 -85.251 31.579 1.661815
 -85.251 31.579 1.661815
 -85.251 31.579 1.661815
 -85.251 31.579 1.661815
 -85.251 31.579 1.661815

接下来,我运行了我的实际kmeans聚类过程。

set.seed(123)
km <- kmeans(input, 12)
cent <- as.data.frame(km$centers)

然后我创建了一个Voronoi Plot来可视化我的数据,如下所示

# Voronoi Plot
V <- deldir(cent$long, cent$lat)
states <- map_data("state")
Statemap <- ggplot() + geom_polygon(data = states, aes(x = long, y = lat, group = group), fill = "light green", col="black")

clust.state <- Statemap + geom_point(data = input, aes(x = long, y = lat), col = factor(km$cluster))
clust.state <- clust.state + geom_label(data = cent, aes(x = long, y = lat), label = row.names(cent))     

clust.state <- clust.state + geom_segment(data = V$dirsgs, aes(x=x1, y = y1, xend = x2, yend = y2), size = 2)

enter image description here

摘要

这并没有完全解决我原来的问题,但我选择发布希望

  1. 接收其他反馈,以便我可以进一步改进(特别是在我的kmeans输入矩阵或Voronoi图上)
  2. 希望它能帮助其他人在自己的地理聚类问题上取得进展