使用K Means算法和Python对地理定位坐标(纬度,长对)进行聚类

时间:2014-07-15 15:38:44

标签: python numpy geolocation scipy k-means

使用以下代码聚类地理位置坐标会产生3个聚类:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.cluster.vq import kmeans2, whiten

    coordinates= np.array([
               [lat, long],
               [lat, long],
                ...
               [lat, long]
               ])
    x, y = kmeans2(whiten(coordinates), 3, iter = 20)  
    plt.scatter(coordinates[:,0], coordinates[:,1], c=y);
    plt.show()

使用Kmeans进行位置聚类是否正确,因为它使用Euclidean distance而非Haversine formula作为距离函数?

2 个答案:

答案 0 :(得分:5)

这在很大程度上取决于您的申请:

  • 在赤道附近,结果应该相当准确。接近其中一个极点,结果将无济于事。
  • 然而,它可以作为预处理步骤或用于具有低精度要求的应用,例如,小的,非重叠的和非常不同的集群。

如果您真的需要Haversine公式,您可能需要查看this讨论。正如Anony-Mousse所说:

  

请注意,Haversine距离不适用于k均值或平均连锁聚类,除非您找到一种智能方法来计算最小化方差的均值。如果纬度 - 经度坐标为-180 / + 180环绕,请不要使用算术平均值。

答案 1 :(得分:5)

由于您的意思,k-means不是用于空间聚类的好算法。相反,您可以使用scikit-learn的DBSCAN使用半正弦度量和球树算法来执行此群集作业。

本教程使用DBSCAN / hasrsine演示clustering latitude-longitude spatial data并避免所有这些欧几里德距离问题:

df = pd.read_csv('gps.csv')
coords = df.as_matrix(columns=['lat', 'lon'])
db = DBSCAN(eps=eps, min_samples=ms, algorithm='ball_tree', metric='haversine').fit(np.radians(coords))

请注意,这特别使用了scikit-learn v0.15,因为某些早期/后期版本似乎需要计算全距离矩阵。另请注意,eps值以弧度为单位,而.fit()采用半径为单位的坐标度量坐标。