我有一组用户。用户数可能是50,也可能是2000。每个人都应该有一个我从Google Geo api中检索到的长/宽。
我需要全部查询它们,并按接近度和一定数量对它们进行分组。假设计数为12,并且该组中有120个用户。我想按人们与他人的相距(远/近)分组。这样我就结识了10个距离很近的人。
我目前拥有Google地理编码api设置,并且希望使用它。
TIA。
-更新 我已经对此进行了一段时间的搜索,看来我正在寻找一个按接近度返回组的空间查询。
答案 0 :(得分:5)
...似乎我正在寻找一个空间查询,该查询按接近程度返回分组。 ...
您可以使用hdbscan。您的组实际上是hdbscan措辞中的群集。您需要使用min_cluster_size和min_samples才能正确设置组。
https://hdbscan.readthedocs.io/en/latest/parameter_selection.html
https://hdbscan.readthedocs.io/en/latest/
看来hdbscan在Python下运行。
以下是有关如何从PHP调用Python的两个链接: Calling Python in PHP, Running a Python script from PHP
以下是有关选择哪种聚类算法的更多信息: http://nbviewer.jupyter.org/github/scikit-learn-contrib/hdbscan/blob/master/notebooks/Comparing%20Clustering%20Algorithms.ipynb
http://scikit-learn.org/stable/modules/clustering.html#clustering
答案 1 :(得分:5)
请记住,这个问题随着您添加的每个用户成倍增长,因为距离计算量与用户数的平方相关(实际上是N*(N-1)
距离...因此有2000个用户群则意味着每趟行程将进行近400万次距离计算。在确定所需资源的大小时请记住这一点
您是要根据直线(实际上是一个大圆)距离还是根据步行/行车距离对它们进行分组?
如果是前者,那么如果您能够忍受很小的误差范围并且希望假设地球是一个球体,则可以用简单的数学方法估算出较大的圆距离。从GCMAP.com:
地球的假想形状称为大地水准面,近似为 椭圆形或扁球形。一个更简单的模型是使用 球体,它非常接近并且使数学更容易。假设 半径6371.2公里的球体,将经度和纬度转换为 弧度(乘以pi / 180),然后使用以下公式:
theta = lon2 - lon1
dist = acos(sin(lat1) × sin(lat2) + cos(lat1) × cos(lat2) × cos(theta))
if (dist < 0) dist = dist + pi
dist = dist × 6371.2
结果距离以公里为单位。
现在,如果您需要精确的计算并且愿意花费很多复杂数学所需的CPU周期,则可以使用Vincenty公式,该公式使用地球的WGS-84参考椭球模型进行导航,映射和没什么。更多信息HERE
对于算法本身,您需要使用每次计算的结果来构建一个“至”矩阵。每行和每列将代表每个节点。您可以考虑以下两种简化方法:
$dist[n][m] == $dist[m][n]
(无需计算整个矩阵,只需计算一半即可)$dist[m][m]
。只要您的所有用户都在地球上,该常量就可以工作)进行所有计算后,使用数组排序方法找到每个节点附近的X个最近节点。 (您可能会或可能不想阻止一个用户分组到多个组中,但这只是业务逻辑)
当前提供的实际代码太多了,没有先看到您的一些进展,但这基本上是您需要通过算法进行的工作。
答案 2 :(得分:0)
使用GeoHash算法[1]。有一个PHP实现[2]。您可以以不同的精度预先计算出地理哈希值,将它们与经纬度值一起存储在SQL数据库中,并使用本机GROUP BY进行查询。