使用df.itertuples()循环调用apply执行getstopscoordinates函数过慢问题排查
问题分析与优化方案
核心问题
- 重复执行全量计算:你写的循环里,每遍历一行(哪怕只取前2行测试),都会对整个
df_RoadSegments执行一次apply,等于把全量计算重复做了2次,完全是无效的重复操作。 apply效率极低:apply本质是逐行迭代,和手动循环没区别,远不如pandas的向量化操作高效。- 函数内的冗余查找:每次调用
getstopscoordinates都要在df_stops里做一次布尔索引查找,没有利用索引来加速匹配。
最优解决方案
直接用merge做关联,全程用pandas向量化操作,速度会提升几个数量级:
步骤1:预处理坐标列
先给df_Stops一次性生成坐标字符串列,避免重复计算:
df_Stops["coordinates"] = df_Stops["stop_lat"].astype(str) + "," + df_Stops["stop_lon"].astype(str)
步骤2:关联数据生成目标列
通过merge把两个表关联起来,直接提取对应坐标:
# 关联RoadSegments和Stops,匹配Origin对应的坐标 df_RoadSegments = df_RoadSegments.merge( df_Stops[["stop_id", "coordinates"]], left_on="RoadSegmentOrigin", right_on="stop_id", how="left" ).rename(columns={"coordinates": "OriginCoordinates"}) # 不需要新增的stop_id列可以删掉 df_RoadSegments.drop("stop_id", axis=1, inplace=True)
原代码错误详解
你原来的循环代码:
for row in df_RoadSegments.head(2).itertuples(): df_RoadSegments["OriginCoordinates"] = df_RoadSegments.apply(lambda x: getstopscoordinates(df_Stops, x["RoadSegmentOrigin"]), axis=1)
哪怕只循环2次,每次都会对**整个df_RoadSegments**执行一遍apply,等于做了2次全量计算。而且apply逐行调用函数,每次都要在df_Stops里做查找,完全浪费了pandas的向量化优势,这就是为什么哪怕测试2行也慢的原因。
额外提速技巧
如果df_Stops数据量很大,给stop_id设置索引可以进一步加速匹配:
df_Stops.set_index("stop_id", inplace=True)
内容的提问来源于stack exchange,提问作者peetman
相关产品推荐
相关产品推荐

