可能是一个非常简单的问题。我列出了大约一千个潜在地理位置(经纬度),其中我需要选择“分布最广泛”的200个位置。我认为那是总平均距离最高的200分。想想城市中的商店。
有定义的方法可以做到吗?也许在R包中?
多亏了每个人,使它成为学习它的好地方!
/克里斯
可能是一个非常简单的问题。我列出了大约一千个潜在地理位置(经纬度),其中我需要选择“分布最广泛”的200个位置。我认为那是总平均距离最高的200分。想想城市中的商店。
有定义的方法可以做到吗?也许在R包中?
多亏了每个人,使它成为学习它的好地方!
/克里斯
Answers:
简单的问题,困难的解决方案。
我知道的最好的方法是使用模拟退火(我已经使用它从数万个中选择了几十个点,并且可以很好地缩放以选择200个点:缩放是次线性的),但这需要仔细的编码和大量的实验,因为以及大量的计算。您应该首先查看更简单,更快速的方法,以查看它们是否足够。
一种方法是首先对商店位置进行聚类。在每个集群中,选择离集群中心最近的商店。
真正快速的聚类方法是K-means。这是R
使用它的解决方案。
scatter <- function(points, nClusters) {
#
# Find clusters. (Different methods will yield different results.)
#
clusters <- kmeans(points, nClusters)
#
# Select the point nearest the center of each cluster.
#
groups <- clusters$cluster
centers <- clusters$centers
eps <- sqrt(min(clusters$withinss)) / 1000
distance <- function(x,y) sqrt(sum((x-y)^2))
f <- function(k) distance(centers[groups[k],], points[k,])
n <- dim(points)[1]
radii <- apply(matrix(1:n), 1, f) + runif(n, max=eps)
# (Distances are changed randomly to select a unique point in each cluster.)
minima <- tapply(radii, groups, min)
points[radii == minima[groups],]
}
的参数scatter
是商店位置的列表(以n ×2矩阵表示)和要选择的商店数量(例如200)。它返回一个位置数组。
作为其应用程序的示例,让我们生成n = 1000个随机定位的商店,并查看解决方案的外观:
# Create random points for testing.
#
set.seed(17)
n <- 1000
nClusters <- 200
points <- matrix(rnorm(2*n, sd=10), nrow=n, ncol=2)
#
# Do the work.
#
system.time(centers <- scatter(points, nClusters))
#
# Map the stores (open circles) and selected ones (closed circles).
#
plot(centers, cex=1.5, pch=19, col="Gray", xlab="Easting (Km)", ylab="Northing")
points(points, col=hsv((1:nClusters)/(nClusters+1), v=0.8, s=0.8))
计算时间为0.03秒:
您可以看到它不是很好(但是也不错)。为了做得更好,将需要要么随机方法,例如模拟退火,要么需要算法,该算法可能会随着问题的大小呈指数增长。(我已经实现了这样的算法:从20个中选择10个间隔最大的点需要12秒。将其应用于200个群集是不可能的。)
分层聚类算法是K均值的一个很好的替代选择。首先尝试“ Ward's”方法,并考虑尝试其他链接。这将需要更多的计算,但是对于1000个存储和200个集群,我们仍然只谈论几秒钟。
存在其他方法。例如,您可以用规则的六边形网格覆盖该区域,对于包含一个或多个商店的单元格,请选择离中心最近的商店。稍微调整一下单元格大小,直到选择了大约200家商店。这将产生非常规则的存储间隔,您可能想要也可能不想要。(如果这些商店确实是商店,这可能是一个糟糕的解决方案,因为它倾向于在人口最少的地区选择商店。在其他应用程序中,这可能是一个更好的解决方案。)