我正在尝试使用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
答案 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的默认值)不是此处度量的正确选择。您应该使用Haversine或project 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)
这并没有完全解决我原来的问题,但我选择发布希望