问题描述
我有一个包含大约 550.000 个数据点的数据块,其中包含经度和纬度。 现在我想确定哪个区域块包含行中的点。有六个区域块,彼此不重叠,我已将其编码为 geopandas 'geometry' 如下:
TMA ... geometry
0 TMA1 ... polyGON ((5.33333 52.80556,5.60944 52.50750,...
1 TMA2 ... polyGON ((4.11806 52.90028,4.35000 52.80528,...
2 TMA3 ... polyGON ((5.07333 52.19583,5.11944 52.20528,...
3 TMA4 ... polyGON ((5.11944 52.20528,5.41972 52.26556,...
4 TMA5 ... polyGON ((5.41972 52.26556,5.60944 52.30306,...
5 TMA6 ... polyGON ((4.35000 52.80528,4.46750 52.75694,...
[6 rows x 4 columns]
为了用正确的面积 (TMA) 值填充我的数据框,我想出了以下代码:
df1['point'] = gp.points_from_xy(df1['LON'],df1['LAT'])
df1['TMA'] = 99
for i in range(0,len(df1)):
for j in range(0,6):
if Schiphol_TMA['geometry'][j].contains(df1['point'][i]):
df1['TMA'][i] = j+1
但是,这需要大量时间。 有没有更聪明的编码方式来加快速度? (是的,我已经阅读了“从不迭代数据帧”......等等)。编辑:也许列表理解可以在这里发挥作用,但是我太初学者了,无法完全掌握那里发生的事情......
解决方法
又是我。我又发现了一个改进。 大多数点 (330.000) 位于 6 个区域之外。所以我首先创建了 6 个区域的轮廓:
SPL_TMA_Contour = Schiphol_TMA.unary_union
然后修改例程,仅当点落在轮廓内时才进行检查:
df1['point'] = gp.points_from_xy(df1['LON'],df1['LAT'])
def f(p):
result = 99
if SPL_TMA_Contour.contains(p):
for T in range(0,6):
if Schiphol_TMA['geometry'][T].contains(p):
result = T+1
break
return result
df1['TMA'] = [f(pt) for pt in df1['point']]
使用时间现在减少到 15.6 秒!骄傲!
,上述例程(包括 break
命令):
df1['TMA'] = 99
for i in range(0,len(df1)):
for j in range(0,6):
if Schiphol_TMA['geometry'][j].contains(df1['point'][i]):
df1['TMA'][i] = j+1
break
以上耗时 86.8 秒(在 Google Colab 上)
当我使用列表理解重写代码如下时:
df1['point'] = gp.points_from_xy(df1['LON'],df1['LAT'])
def f(p):
for T in range(0,6):
if Schiphol_TMA['geometry'][T].contains(p):
result = T+1
break
else:
result = 99 # not in any area
return result
df1['TMA'] = [f(pt) for pt in df1['point']]
这个新例程耗时 45.9 秒。大约一半。 我开始学... 也许这可以做得更快?