Python 通过dataframe迭代调用GoogleDistanceAPI的最佳方法

Python 通过dataframe迭代调用GoogleDistanceAPI的最佳方法,python,database,pandas,api,Python,Database,Pandas,Api,我想知道从google maps distance API获取距离的最佳解决方案是什么,我的数据框由坐标(原点和终点)组成,大约75k行 #Origin #Destination 1 (40.7127837, -74.0059413) (34.0522342, -118.2436849) 2 (41.8781136, -87.6297982) (29.7604267, -95.3698028) 3 (39.9525839, -

我想知道从google maps distance API获取距离的最佳解决方案是什么,我的数据框由坐标(原点和终点)组成,大约75k行

    #Origin                     #Destination

1   (40.7127837, -74.0059413)   (34.0522342, -118.2436849)
2   (41.8781136, -87.6297982)   (29.7604267, -95.3698028)
3   (39.9525839, -75.1652215)   (40.7127837, -74.0059413)
4   (41.8781136, -87.6297982)   (34.0522342, -118.2436849)
5   (29.7604267, -95.3698028)   (39.9525839, -75.1652215)
到目前为止,我的代码遍历dataframe并调用API,将距离值复制到新的“distance”列中

我得到了期望的结果,但是从我读到的内容来看,遍历dataframe效率很低,应该避免。240行需要20秒,因此需要1h30才能完成所有数据帧。请注意,一旦完成,就不需要再重新运行了,每月只需新增几行(~500行)

在这里,我们最好的解决方案是什么


编辑:如果有人对google distance API及其限制有经验,欢迎提供任何提示/最佳实践。

我试图了解并发调用的任何限制,但我找不到任何东西。几点建议

避免循环 关于你的代码,我宁愿跳过循环,先使用apply

def get_gmaps_距离(行):
结果=gmaps.距离矩阵(第['origin']行、第['destination']行、模式='driving')
状态=结果['rows'][0]['elements'][0]['status']
如果状态==“正常”:
KM=int(结果['rows'][0]['elements'][0]['distance']['value']/1000)
其他:
公里=0
返回公里
df[“距离”]=df.apply(获取gmaps距离,轴=1)
拆分数据帧并使用多处理
将多处理导入为mp
def parallelize(fun、vec、cores=mp.cpu\u count()):
mp.池(核心)作为p:
res=p.map(乐趣,vec)
返回res
#根据核心数将数据帧拆分为多个块
df=np.array\u split(df,mp.cpu\u count())
#这将为每个chunck使用您的函数
def平行距离(x):
x[“距离”]=x.apply(获取gmaps距离,轴=1)
返回x
df=平行化(平行距离,df)
df=pd.concat(df,ignore_index=True,sort=False)
不要计算两次相同的距离(保存$$) 如果您有重复的行,您应该删除其中一些

grp=df.drop\u重复项([“源”、“目标”])。重置索引(drop=True)
这里我没有覆盖df,因为它可能包含您需要的更多信息,您可以将结果合并到其中

grp[“distance”]=grp.apply(获取gmaps\u距离,轴=1)
df=pd.merge(df,grp,how=“left”)
减少小数 你应该问你这个问题:我真的需要精确到小数点后7位吗?由于1度纬度约为111km,小数点后第7位的精度最高可达1cm。你可以从中得到一个想法,减少小数,他们改进了模型

结论
如果您最终能够使用所有建议的方法,您可能会得到一些有趣的改进。我希望您在这里发表评论,因为我没有个人API密钥可供自己尝试。

非常感谢您的评论,它超出了我的预期,并澄清了我想要尝试的内容。最后,我使用了您给我的所有提示:将for循环丢弃到您提供的函数中,使用拆分和多重处理(注意,我必须添加“if name=='main':”以避免错误消息),删除重复的,并将小数减少到4。Dataframe被划分为4个部分,对于总共+50k个请求,它花费的时间不到20分钟!这是完美的,在这个过程中教会了我很多,所以再次感谢你。
df['distance'] = ""

for index, row in df.iterrows():
    result = gmaps.distance_matrix(row['origin'], row['destination'], mode='driving')
    status = result['rows'][0]['elements'][0]['status']
    if status == "OK":                               # Handle "no result" exception
        KM = int(result['rows'][0]['elements'][0]['distance']['value'] / 1000)
        df['distance'].iloc[index] = KM
    else:
        df['distance'].iloc[index] = 0

df.to_csv('distance.csv')