基于经纬度矩阵计算距离矩阵

给定一个矩阵,计算距离矩阵是一个非常常见的需求,比如给定一个特征矩阵需要计算距离矩阵。自己写的话虽然简单每次写也往往很烦,而且自己写的代码效率过低了,使用scipy中的包的话无疑会好一点,具体来说,使用scipy.spatial.distance,该包的具体介绍可以看一下官网和这个博客。
下面贴一个我写的基于经纬度矩阵,计算两两间的距离的代码:
具体矩阵的形式是一个dataframe,一列是经度,一列是纬度,如下图所示,下面代码中的cam就是这个dataframe。
在这里插入图片描述

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial.distance import pdist
from scipy import spatial
import math

# 定义通过经纬度计算直线距离的函数
from math import radians, cos, sin, asin, sqrt
def geodistance(lng1,lat1,lng2,lat2):
    if lng1 == None or lng2 == None or lat1 == None or lat2 == None:
        return 999999
    elif (lng1 < 119 or lng1 > 121) or (lng2 < 119 or lng2 > 121) or (lat1 < 29 or lat1 > 30) or (lat2 < 29 or lat2 > 30):
        return 999999
    lng1 = float(lng1) ; lng2 = float(lng2) ; lat1 = float(lat1) ; lat2 = float(lat2)
    lng1,lat1,lng2,lat2 = map(radians,[lng1,lat1,lng2,lat2])
    dlon = lng2-lng1
    dlat = lat2-lat1
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    distance = 2* asin(sqrt(a))*6371*1000
    distance = round(distance/1000,3)
    return distance
def caldis(u,v):
    # 计算输入矩阵中两个向量的距离
    return geodistance(u[0],u[1],v[0],v[1])
    
# 将cam转化为向量的形式
X = cam.values
X_mat = spatial.distance.squareform(pdist(X , metric=caldis))

上面代码得到的X_mat就是每两个经纬度点之间的直线距离了。
下面我还希望求出这个距离矩阵中每一行中距离小于等于1的个数,并将这个个数保存到dataframe cam中去,代码如下:

def sma1(ser):
    return (len(ser[ser<=1]))
cam['devdes'] = np.apply_along_axis(sma1, 1, X_mat)

如果不是一个矩阵各个样本两两间的距离,而是两个矩阵两两间的距离,则可以使用函数from scipy.spatial.distance import cdist,代码如下:

X_mat = cdist(cam[['lng','lat']].values , tmp[['lng','lat']].values , metric=caldis)

得到的结果是len(cam[[‘lng’,‘lat’]])行,len(tmp[[‘lng’,‘lat’]].values)列的一个矩阵,第i,j个元素代表的含义是cam[[‘lng’,‘lat’]]第i行和tmp[[‘lng’,‘lat’]]第j列两个元素的距离。

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个基于经纬度距离的KMeans聚类代码示例: ```python import pandas as pd import numpy as np from sklearn.cluster import KMeans from sklearn.metrics import pairwise_distances_argmin_min from math import radians, cos, sin, asin, sqrt # 读取经纬度数据 df = pd.read_csv('data.csv') # 文件中包含两列:经度和纬度 # 经纬度距离计算函数 def haversine(lon1, lat1, lon2, lat2): """ Calculate the great circle distance between two points on the earth (specified in decimal degrees) """ # 将十进制度数转化为弧度 lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) # haversine公式 dlon = lon2 - lon1 dlat = lat2 - lat1 a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 c = 2 * asin(sqrt(a)) r = 6371 # 地球平均半径,单位为公里 return c * r # 计算每个点之间的距离矩阵 dist_matrix = np.zeros((len(df), len(df))) for i in range(len(df)): for j in range(i+1, len(df)): dist = haversine(df.iloc[i]['lon'], df.iloc[i]['lat'], df.iloc[j]['lon'], df.iloc[j]['lat']) dist_matrix[i][j] = dist dist_matrix[j][i] = dist # KMeans聚类 kmeans = KMeans(n_clusters=3, random_state=0).fit(dist_matrix) # 找到每个簇中最近的数据点 closest_points = pairwise_distances_argmin_min(kmeans.cluster_centers_, dist_matrix) # 输出每个簇的中心点和最近的数据点 for i in range(len(kmeans.cluster_centers_)): print('Cluster', i) print('Center:', kmeans.cluster_centers_[i]) print('Closest point:', df.iloc[closest_points[0][i]]) ``` 该代码会首先读取一个包含经度和纬度数据的CSV文件(文件路径为`data.csv`),然后计算每个点之间的距离矩阵。接着使用KMeans算法将这些点聚类为3个簇,并找到每个簇中距离簇中心最近的数据点。最后输出每个簇的中心点和最近的数据点。需要注意的是,该代码中使用的距离计算函数是基于经纬度的哈弗曼公式。如果你的数据集比较大,可以考虑使用更高效的距离计算方法。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值