加速通过两个Pandas数据帧的嵌套for循环

2024-09-26 17:52:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我在pandas数据框(df)中存储了一个纬度和经度,填充点为NaN,表示stop_id, stoplat, stoplon,另一个数据框areadf,它包含更多的纬度/经度和一个任意的id;这是要填充到df中的信息。在

我试图将这两个连接起来,以便df中的stop列包含与该lat/lon点最近的stop有关的信息,或者如果在该点的半径R内没有停止,则将其保留为NaN。在

现在我的代码如下所示,但它需要相当长的时间(在将区域更改为df并使用itertuples之前,我正在运行的代码大约需要40分钟;不确定这将产生多大的差异?)因为每一组数据有数千个lat/lon点和停止,这是一个问题,因为我需要在多个文件上运行这个。我在找建议让它运行得更快。我已经做了一些非常小的改进(例如,移动到一个数据帧,使用itertuples代替iterrows,在循环之外定义lat和lon,以避免在每个循环上都必须从df中检索它),但是我没有办法加快它的速度。getDistance使用定义的Haversine公式来获得停止标志和给定的lat,lon点之间的距离。在

import pandas as pd
from math import cos, asin, sqrt

R=5
lats = df['lat']
lons = df['lon']
for stop in areadf.itertuples():
    for index in df.index:
        if getDistance(lats[index],lons[index],
                       stop[1],stop[2]) < R:
            df.at[index,'stop_id'] = stop[0] # id
            df.at[index,'stoplat'] = stop[1] # lat
            df.at[index,'stoplon'] = stop[2] # lon

def getDistance(lat1,lon1,lat2,lon2):
    p = 0.017453292519943295     #Pi/180
    a = (0.5 - cos((lat2 - lat1) * p)/2 + cos(lat1 * p) * 
         cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2)
    return 12742 * asin(sqrt(a)) * 100

样本数据:

^{pr2}$

期望:

df
lat        lon         stop_id    stoplat    stoplon
43.657676  -79.380146  0          43.657675  -79.380145
43.694324  -79.334555  NaN        NaN        NaN

Tags: 数据iddfindexcosnanatstop
1条回答
网友
1楼 · 发布于 2024-09-26 17:52:29

一种方法是使用来自here的numpy haversine函数,只需稍作修改,就可以计算出所需的半径。在

只需使用apply遍历您的df,并在给定半径内找到最接近的值

def haversine_np(lon1, lat1, lon2, lat2,R):
    """
    Calculate the great circle distance between two points
    on the earth (specified in decimal degrees)
    All args must be of equal length.    
    """
    lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = np.sin(dlat/2.0)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2.0)**2
    c = 2 * np.arcsin(np.sqrt(a))
    km = 6367 * c
    if km.min() <= R:
        return km.argmin()
    else:
        return -1

df['dex'] = df[['lat','lon']].apply(lambda row: haversine_np(row[1],row[0],areadf.stoplon.values,areadf.stoplat.values,1),axis=1)

然后合并两个数据帧。在

^{pr2}$

注意:如果选择使用此方法,则必须确保两个数据帧索引都已重置,或者它们是从0到df的总长度顺序排列的。所以在运行这个之前一定要重置索引。在

df.reset_index(drop=True,inplace=True)
areadf.reset_index(drop=True,inplace=True) 

相关问题 更多 >

    热门问题