在 R 中复制聚类过程
Replicating a Clustering Procedure in R
我正在尝试使用 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 函数计算非欧几里得距离。我无法理解这段话的确切含义:
"With k-means, each coordinate is first weighted proportionally to its frequency at both the origin and destination. Then according to a predetermined number, clusters are formed by minimizing the weighted distance between coordinates."
对于每个不同的始发地和目的地(纬度、经度)组合,我可以计算它同时作为目的地和始发地出现的频率,然后将其乘以平均装运距离吗?在考虑起点和终点之间的关系的同时,我不确定如何在二维中执行 k-means 算法。
lat long Dist*Vol
34.271 -86.217 226.6021
30.889 -87.776 400
. . .
. . .
. . .
31.158 -88.016 1301.85
看起来您基于 5 个不同的特征进行聚类 - Olong、Olat、Dlong、Dlat 和 Dist.Vol。
如果你想创建空间集群,你只需要有两个特征。如果我理解正确,你应该将 Olong 与 Dlong 和 Olat 与 Dlat rbind。
data <- data.frame(lat = c(data$Olat,data$Dlat), lon = c(data$Olong,data$Dlong)
然后你可以在这个二维上应用 k-means space。
results <- kmeans(data, 20)
请注意,使用欧几里德距离(k-means 的默认值)不是此处度量的正确选择。你应该使用 Haversine or project your points to a Cartesian space.
关于可视化——设置 k-means 后,您可以绘制质心 + a Voronoi diagram. Looks like this is the case in the paper. See this question 以获得更多详细信息:
更新
我决定只关注大量出境装运区域,从而在某种程度上简化了我的问题。现在,我的输入数据带有 5,000
个不同的城市,并附有平均统计数据 CPM
= 每英里成本和 Volume
= 出境货运数量。
Oid Long Lat CPM Volume
203 -85.251 31.579 1.661 97
. . . . .
我想根据地理距离和每英里平均出境成本进行聚类。为了考虑到数量,我根据出货量 Volume
在我的输入矩阵中复制了每个 Oid
(始发城市)。为此,我使用了以下代码:
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)
总结
这并不能完全解决我原来的问题,但我选择 post 希望
- 收到额外的反馈,以便我可以进行进一步的改进(特别是在我的 kmeans 输入矩阵或 Voronoi 图上)
- 希望它能帮助其他人在他们自己的地理聚类问题上取得进展
我正在尝试使用 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 函数计算非欧几里得距离。我无法理解这段话的确切含义:
"With k-means, each coordinate is first weighted proportionally to its frequency at both the origin and destination. Then according to a predetermined number, clusters are formed by minimizing the weighted distance between coordinates."
对于每个不同的始发地和目的地(纬度、经度)组合,我可以计算它同时作为目的地和始发地出现的频率,然后将其乘以平均装运距离吗?在考虑起点和终点之间的关系的同时,我不确定如何在二维中执行 k-means 算法。
lat long Dist*Vol
34.271 -86.217 226.6021
30.889 -87.776 400
. . .
. . .
. . .
31.158 -88.016 1301.85
看起来您基于 5 个不同的特征进行聚类 - Olong、Olat、Dlong、Dlat 和 Dist.Vol。
如果你想创建空间集群,你只需要有两个特征。如果我理解正确,你应该将 Olong 与 Dlong 和 Olat 与 Dlat rbind。
data <- data.frame(lat = c(data$Olat,data$Dlat), lon = c(data$Olong,data$Dlong)
然后你可以在这个二维上应用 k-means space。
results <- kmeans(data, 20)
请注意,使用欧几里德距离(k-means 的默认值)不是此处度量的正确选择。你应该使用 Haversine or project your points to a Cartesian space.
关于可视化——设置 k-means 后,您可以绘制质心 + a Voronoi diagram. Looks like this is the case in the paper. See this question 以获得更多详细信息:
更新
我决定只关注大量出境装运区域,从而在某种程度上简化了我的问题。现在,我的输入数据带有 5,000
个不同的城市,并附有平均统计数据 CPM
= 每英里成本和 Volume
= 出境货运数量。
Oid Long Lat CPM Volume
203 -85.251 31.579 1.661 97
. . . . .
我想根据地理距离和每英里平均出境成本进行聚类。为了考虑到数量,我根据出货量 Volume
在我的输入矩阵中复制了每个 Oid
(始发城市)。为此,我使用了以下代码:
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)
总结
这并不能完全解决我原来的问题,但我选择 post 希望
- 收到额外的反馈,以便我可以进行进一步的改进(特别是在我的 kmeans 输入矩阵或 Voronoi 图上)
- 希望它能帮助其他人在他们自己的地理聚类问题上取得进展