【发布时间】:2021-12-26 08:34:09
【问题描述】:
我在 python 中有两个数据框:一个 ~150k 调用,每个都有一个地理位置,另一个 ~50k streets,每个都有一个地理路径。给定每个呼叫的位置,我想将最近街道的头节点 ID 和尾节点 ID 附加到呼叫数据帧。
我已经阅读了通话数据并转换了数字纬度/经度列并构建了一个单一的 Shapely Point 列。同样,我已将字符串路径数据列转换为 Shapely LineString。这些是下面的算法一和二 - 不太可能是最有效的实现。欢迎您的 cmets。
% Algorithm One: given two columns of latitude & longitude, create a new Point
def call_iter():
points = []
for index, row in calls.iterrows():
points.append(Point(row['Incident Latitude'], row['Incident Longitude']))
return points % appended to the call dataframe
% Algorithm Two: given a string column containing coordinate data, construct a LineString
def street_iter():
paths = []
for geo in streets.geometry:
l = []
for t in geo.split():
try:
t = t.strip('(,)')
l.append(float(t))
except ValueError:
pass
p = []
for i in range(0, len(l), 2):
p.append(Point(l[i], l[i+1]))
paths.append(LineString(p))
return paths % appended to the street dataframe
然而,我主要关心的是第一段中概述的问题:鉴于 Shapely 方法 line.distance(point) 和新创建的 Shapely 对象,我如何有效地找到离每个呼叫最近的街道?我一天的尝试如下所示。这确实有效,但每次调用需要 1-2 秒,这是我想使用的几个数据集中的第一个。
% Algorithm Three: find the closest street (head 'u' and tail 'v' nodes) to each call
def build_matrix():
heads = []
tails = []
for i_c, r_c in calls.iterrows():
print(i)
p = r_c[4]
head_min = -1
tail_min = -1
dist_min = float('inf')
min_group = []
for i_s, r_s in streets.iterrows():
l = r_s[5].distance(p)
if dist_min > l:
head_min = r_s['u'] % head node
tail_min = r_s['v'] % tail node
dist_min = l
min_group = []
min_group.append(r_s)
if dist_min == l:
min_group.append(r_s)
if len(min_group) > 1:
choice = secrets.choice(min_group) % randomly selects an arc
head_min = choice['u']
tail_min = choice['v']
heads.append(head_min)
tails.append(tail_min)
return (heads, tails) % both appended to the calls dataframe
我已经花了几个小时研究矢量化,但是我找不到此类事情的任何示例。非常感谢您的帮助。
【问题讨论】:
-
我花了一上午的时间来实现Tenkanen et al 的工作。这似乎并没有太多地提高效率。每次迭代可能不到一秒。
标签: python pandas dataframe vectorization shapely