計算經緯度的代碼網上一搜一大把,通常是單點距離的計算,無法實現批量計算,本文將利用pandas實現億級經緯度距離代碼的實現。
本文將實現兩張表的任意點之間100、200、300、500、800、1000米範圍內的距離計算。
首先導入需要使用的包
1importpandasaspd
2importnumpyasnp
3frommathimportradians, cos, sin, asin, sqrt, ceil
4importmath
5importtime
經緯度計算自定義函數
1defgeodistance(lng1,lat1,lng2,lat2):
2lng1, lat1, lng2, lat2 = map(radians, [float(lng1), float(lat1), float(lng2), float(lat2)])
3# 經緯度轉換成弧度
4dlon=lng2-lng1
5dlat=lat2-lat1
6a=sin(dlat/2)**2+ cos(lat1) * cos(lat2) * sin(dlon/2)**2
7distance=2*asin(sqrt(a))*6371*1000# 地球平均半徑,6371km
8distance=round(distance,)
9returndistance
實現不同範圍內的距離計算,例如100、200、300、500、800、1000,適合做成一張參數表。
由於地球是球形,不同緯度下,同一經度差值對應的距離不同,緯度相同且緯度越大時,同一經度對應的距離越小,中國經緯度跨度約為,此處為了計算最大經度差值,我們選取緯度為;不同經度下,同一緯度差異對應的距離相同
不同經緯度差異對應最小距離表格如下:
分別導入源表和目標表,兩個表關聯得到原點與目標點的所有配對
1file_name =r'D:\python\geo\sTable.csv'
2df1=pd.read_csv(file_name)
3file_name2 =r'D:\python\geo\tTable.csv'
4df2=pd.read_csv(file_name2)
5m = pd.concat([pd.concat([df1]*len(df2)).sort_index().reset_index(drop=True),
6pd.concat([df2]*len(df1)).reset_index(drop=True) ],1)
然後根據經度和緯度差值進行過濾(經緯度差值大於某個值,距離大於某個值,參見參數表
得到下圖表格:
然後針對每一行的4個參數應用自定義函數,此處使用內置模塊(比使用循環要高效很多)。
根據經緯度差值判斷距離是一個大致的範圍,我們選取緯度值獲取了最大的經度差值,隨著緯度減小,此時計算的距離會大於該閾值,所以要對初次計算結果進行過濾,得出滿足閾值的條目:
1distance = distance.append(nn[nn.distance
經過調試,發現該方法計算量上限基本為萬,當計算量大於萬怎麼辦?
偶然間想起了之前自己將文件分割的文章,當計算量大於萬,我們對原表進行分割,分割個數就是,不能整除時,需要先上取整,多分割一個文件
分割數目有了,文件分片大小也就有了
1linesPerFile = ceil(count_a / pieces)+1
文件分割代碼:
1filecount =1
2# 以0為起點,文件行數為終點,分片大小為間隔,循環遍歷文件,每次遍歷行數即為分片大小,而不是每行遍歷一次,處理效率極高,但是比較吃內存
3foriinrange(, len(csv_file), linesPerFile):
4# 打開目標文件準備寫入,不存在則創建
5withopen(file_name[:-4] +'_'+ str(filecount) +'.csv','w+')asf:
6# 判斷是否為第一個文件,不是的話需要先寫入標題行
7iffilecount >1:
8f.write(csv_file[])
9# 批量寫入i至i+分片大小的多行數據,效率極高
10f.writelines(csv_file[i:i+linesPerFile])
11# 完成一個文件寫入之後,文件編號增加1
12filecount +=1
詳情可以參考如下文章。
將文件分割之後,我們便可以循環處理分片文件與目標文件,將得到的結果合併到一個空的裡st_time)))
使用測試數據測算,經緯度距離億次計算量耗時約秒,秒殺VBA。