【发布时间】:2020-08-24 08:59:50
【问题描述】:
是否有更快的方法(在 Python 中,使用 CPU)来执行与以下函数相同的操作?我使用了For 循环和if 语句,想知道是否有更快的方法?目前每 100 个邮政编码需要大约 1 分钟来运行此功能,而我大约有 70,000 个要通过。
使用的 2 个数据框是:
postcode_df 包含 71,092 行和列:
- 邮政编码例如“BL4 7PD”
- 纬度,例如53.577653
- 经度,例如-2.434136
例如
postcode_df = pd.DataFrame({"Postcode":["SK12 2LH", "SK7 6LQ"],
"Latitude":[53.362549, 53.373812],
"Longitude":[-2.061329, -2.120956]})
air 包含 421 行和列:
- TubeRef 例如“ABC01”
- 纬度,例如53.55108
- 经度,例如-2.396236
例如
air = pd.DataFrame({"TubeRef":["Stkprt35", "Stkprt07", "Stkprt33"],
"Latitude":[53.365085, 53.379502, 53.407510],
"Longitude":[-2.0763, -2.120777, -2.145632]})
该函数循环遍历 postcode_df 中的每个邮政编码,并为每个邮政编码循环遍历每个 TubeRef 并计算(使用geopy)它们之间的距离,并保存与邮政编码距离最短的 TubeRef。
输出 df,postcode_nearest_tube_refs,包含每个邮政编码最近的管并包含列:
- 邮政编码例如“BL4 7PD”
- 最近的空气管,例如"ABC01
- 到空气管 KM 的距离,例如1.035848
# define function to get nearest air quality monitoring tube per postcode
def get_nearest_tubes(constituency_list):
postcodes = []
nearest_tubes = []
distances_to_tubes = []
for postcode in postcode_df["Postcode"]:
closest_tube = ""
shortest_dist = 500
postcode_lat = postcode_df.loc[postcode_df["Postcode"]==postcode, "Latitude"]
postcode_long = postcode_df.loc[postcode_df["Postcode"]==postcode, "Longitude"]
postcode_coord = (float(postcode_lat), float(postcode_long))
for tuberef in air["TubeRef"]:
tube_lat = air.loc[air["TubeRef"]==tuberef, "Latitude"]
tube_long = air.loc[air["TubeRef"]==tuberef, "Longitude"]
tube_coord = (float(tube_lat), float(tube_long))
# calculate distance between postcode and tube
dist_to_tube = geopy.distance.distance(postcode_coord, tube_coord).km
if dist_to_tube < shortest_dist:
shortest_dist = dist_to_tube
closest_tube = str(tuberef)
# save postcode's tuberef with shortest distance
postcodes.append(str(postcode))
nearest_tubes.append(str(closest_tube))
distances_to_tubes.append(shortest_dist)
# create dataframe of the postcodes, nearest tuberefs and distance
postcode_nearest_tube_refs = pd.DataFrame({"Postcode":postcodes,
"Nearest Air Tube":nearest_tubes,
"Distance to Air Tube KM": distances_to_tubes})
return postcode_nearest_tube_refs
我正在使用的库是:
import numpy as np
import pandas as pd
# !pip install geopy
import geopy.distance
【问题讨论】:
-
使用示例输入和预期输出更新了您的帖子
-
geopandas 包提供空间索引。 Lesson 3 of the AutoGIS 2019 course 涵盖地理编码和 r-trees 的使用。
-
不要计算全距离矩阵,使用 BallTree 算法。 scikit-learn.org/stable/modules/generated/… 它支持半正弦距离,并且比全距离矩阵要好得多。我的猜测是这需要几秒钟/几分钟。如果您需要一个完整的工作示例,请告诉我。请提供一些对熊猫友好的数据行
-
@user3184950 (stackoverflow.com/users/3184950/user3184950) 谢谢。我已经用 Pandas 代码更新了这个问题,用于创建带有一些示例行的输入数据框。这能满足你的需要吗?很高兴看到一个完整的工作示例。
-
是的,这有帮助。我发布了它,结果不到 10 秒。
标签: python performance geopy