|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 txl1988 于 2021-4-2 09:23 编辑
工作需要,计算经纬度间的距离之前都是用别人的vba,这不咱也认真学了小甲鱼的Python嘛,所以尝试着用Python来完成
csv表结构非常简单,就三列 [Name Longitude Latitude ]
用了两种方法,第一种方法,用 for ,数据量非常的时候,计算的速度还能接受,但是1000*1000的数据,就计算不出来了(用了半天没出结果就取消了)
通过学习得到第二种方法,速度真快,还是1000*1000的数据,1分钟不到
那废话不多说,上干活
求大佬指点,怎么样设计(修改)代码,看上去更加专业点呢
方法一:不推荐啊,只做一种失败的思路参考
- # -*- coding: utf-8 -*-
- """
- Created on Tue Dec 22 10:35:30 2020
- @author: Administrator
- 多个经纬度距离计算
- 1、修改man函数里面,涉及路径和文件名,其他部分不做修改,执行结果的距离单位为 米m
- 2、输入文件列名,Name,Longitude,Latitude(Name就是这个经纬度的标识,可以是基站,小区,eci等等)
- """
- from math import pi, asin, sqrt, sin, cos, pow
- import pandas as pd
- from pandas import DataFrame
- import time
- def rad(d):
- # math.pi = 圆周率π
- return d * pi / 180.0
- def getDistance(lat1, lng1, lat2, lng2):
- # 计算两个经纬度之间的距离
- # 地球半径 km 6371.393和6378.137,一般取值6371.393
- EARTH_REDIUS = 6371393
- radLat1 = rad(lat1)
- radLat2 = rad(lat2)
- # 计算两个经度/维度之差,调用上边rad(d)函数
- a = rad(lat1) - rad(lat2)
- b = rad(lng1) - rad(lng2)
- s = 2 * asin(sqrt(pow(sin(a/2), 2) + cos(radLat1) * cos(radLat2) * pow(sin(b/2), 2)))
- s = s * EARTH_REDIUS
- # 格式化字符串,保留2位小数
- # s = '%.2f' % s
- return s
- def data(l1,l2):
- # 计算所有经纬度之间的距离
- new_df = DataFrame(columns=['Name_1','Latitude_1','Longitude_1',
- 'Name_2','Latitude_2','Longitude_2',
- 'Distance_m'])
-
- for a,b in l1.iterrows():
- for c,d in l2.iterrows():
- lat1 = b['Latitude']
- lng1 = b['Longitude']
- name1 = b['Name']
-
- lat2 = d['Latitude']
- lng2 = d['Longitude']
- name2 = d['Name']
-
- # 距离计算
- jl = getDistance(lat1, lng1, lat2, lng2)
- # 创建新表临时保存
- row = DataFrame([dict(Name_1=name1, Latitude_1=lat1, Longitude_1=lng1,
- Name_2=name2, Latitude_2=lat2, Longitude_2=lng2,
- Distance_m = jl), ])
-
-
- # =============================================================================
- # # 这一步要对row的列名进行排序,否则会有提示信息,强迫症看着不舒服,append 排序是因为非连接轴未对齐,或者添加sort=False参数忽略
- # row = row[['Name_1','Latitude_1','Longitude_1',
- # 'Name_2','Latitude_2','Longitude_2',
- # 'Distance_m']]
- # =============================================================================
-
- # append ,ignore_index=True 根据列名字段对齐,然后合并。最后再重新整理一个新的index。
- new_df = new_df.append(row,ignore_index=True,sort=True)
- new_df = new_df.sort_values(by="Distance_m", ascending=True)
- new_df.drop_duplicates(subset=['Name_1'],keep='first',inplace=True)
- # =============================================================================
- # # 如果只对小于n的距离,进行保存,需要加个判断条件,例小于3km
- # if row['Distance_m'].values < 44000:
- # new_df = new_df.append(row,ignore_index=True,sort=True)
- #
- # =============================================================================
-
- #默认排序是按照字母升序(a,b,c,d...),此代码是指定排序方式
- new_df=new_df[['Name_1','Latitude_1','Longitude_1',
- 'Name_2','Latitude_2','Longitude_2',
- 'Distance_m']]
-
- # # 取最近距离
- # #https://developer.aliyun.com/article/705184
- # # 按照距离,升序(小到大)
- # new_df = new_df.sort_values(by="Distance_m", ascending=True)
- # # 去重
- # new_df.drop_duplicates(subset=['Name_1'],keep='first',inplace=True)
- #
-
-
- return new_df
- def main():
- starttime = time.time()
- # print("两点间的距离为:%.2f km" %jl)
- path_1 = r"C:\Users\Administrator\练习\经纬度距离计算1.csv"
-
- l1 = pd.read_csv(path_1, encoding='gbk', engine='python')
- path_2 = r"C:\Users\Administrator\练习\经纬度距离计算2.csv"
-
- l2 = pd.read_csv(path_2, encoding='gbk', engine='python')
- result = data(l1,l2)
-
- result.to_csv(r'C:\Users\Administrator\练习\经纬度距离结果.csv',index=0,encoding='gbk')
- print("finish")
-
- if __name__ == "__main__":
- print('start...')
- main()
复制代码
方法二:强烈推荐哦
- # -*- coding: utf-8 -*-
- """
- Created on Wed Mar 31 16:36:47 2021
- @author: Administrator
- """
- # -*- coding: utf-8 -*-
- """
- Created on Tue Dec 22 10:35:30 2020
- @author: Administrator
- 多个经纬度距离计算
- 1、修改man函数里面,涉及路径和文件名,其他部分不做修改,执行结果的距离单位为 米m
- 2、输入文件列名,Name,Longitude,Latitude(Name就是这个经纬度的标识,可以是基站,小区,eci等等)
- """
- from math import pi, asin, sqrt, sin, cos, pow
- import pandas as pd
- from pandas import DataFrame
- import numpy as np
- import time
- def rad(d):
- # math.pi = 圆周率π
- return d * pi / 180.0
- def getDistance(lat1, lng1, lat2, lng2):
- # 计算两个经纬度之间的距离
- # 地球半径 km 6371.393和6378.137,一般取值6371.393
- EARTH_REDIUS = 6371393
- # 上边rad()函数可以转换成 rad = lambda d:d * pi / 180.0
- radLat1 = rad(lat1)
- radLat2 = rad(lat2)
- # 计算两个经度/维度之差,调用上边rad(d)函数
- a = rad(lat1) - rad(lat2)
- b = rad(lng1) - rad(lng2)
- s = 2 * asin(sqrt(pow(sin(a/2), 2) + cos(radLat1) * cos(radLat2) * pow(sin(b/2), 2)))
- s = s * EARTH_REDIUS
- # 格式化字符串,保留2位小数
- # s = '%.2f' % s
- return s
- def data(l1,l2):
- # 计算所有经纬度之间的距离
- #构造共同的列,赋予同样的值
- l1['value']=1
- l2['value']=1
-
- #将两个数据集进行左连接,笛卡尔积
- Crt_prod=pd.merge(l1,l2,how='left',on='value')
- del Crt_prod['value']
- # #可以修改列名
- # a.rename(columns={'A':'a', 'B':'b', 'C':'c'}, inplace = True)
-
- # 调用计算距离的函数,此处体现能力的时候,之前使用两个for循环,数据多时计算不出来,通过查询,此方法大大节约了时间
- Crt_prod['distance']=Crt_prod.apply(lambda ser: getDistance(ser['Latitude_x'], ser['Longitude_x'], ser['Latitude_y'], ser['Longitude_y']),axis=1)
- # =============================================================================
- #如果需要得到到与path_2的哪个位置点与path_1每个位置点的距离最近,运行下面的代码
- #按照distance升序排列,按照name_x 去重
- Crt_prod = Crt_prod.sort_values(by="distance", ascending=True)
- # # 去重
- Crt_prod.drop_duplicates(subset=['Name_x'],keep='first',inplace=True)
-
- # =============================================================================
-
- ## =============================================================================
- # #如果按照两点的距离,去除超远距离的,执行此处,主要现在的单位是米
- #
- # Crt_prod = Crt_prod[Crt_prod['distance'] < 100]
- #
- #
- ## =============================================================================
- return Crt_prod
- def main():
- starttime = time.time()
- # print("两点间的距离为:%.2f km" %jl)
- path_1 = r"C:\Users\Administrator\练习\经纬度距离计算1.csv"
- l1 = pd.read_csv(path_1, encoding='gbk', engine='python')
- path_2 = r"C:\Users\Administrator\练习\经纬度距离计算2.csv"
- l2 = pd.read_csv(path_2, encoding='gbk', engine='python')
- result = data(l1,l2)
-
- result.to_csv(r'C:\Users\Administrator\练习\经纬度距离结果.csv',index=0,encoding='gbk')
-
- print("finish")
- endtime=time.time()
- cost_time = endtime - starttime
- print('处理完成,程序运行时间: {}秒'.format(float('%.2f' % cost_time)))
-
- if __name__ == "__main__":
- print('start...')
- main()
复制代码
|
|