如何转换pandas中的lat / lon点并查看它们是否属于某些边界多边形?

时间:2016-09-14 23:54:35

标签: python pandas matplotlib geopandas

我有一个像这样的Pandas数据帧df

 id   lat  lon
 jhg  2.7  3.5
 ytr  3.1  3.5
 ...

我还有一些带有一些多边形的Geopandas数据帧poly。现在,我想只绘制df里面某个多边形的点。所以我应该可以执行类似poly.intersects(p)的操作,其中p是一个Shapely Point。但我做错了什么;

from shapely.geometry import Point
for index, row in df.iterrows():
    t = poly.intersects(Point(row.lon, row.lat))

使用lat / lon点传递数据帧并将其覆盖到poly的最佳方法是什么?请注意,我可以定义最小/最大纬度/经度范围,但也会在poly之外但在(更大)边界框内打印点。

2 个答案:

答案 0 :(得分:1)

您的出发点:

import pandas as pd
from shapely.geometry import box
import matplotlib.pyplot as plt

from matplotlib.collections import PatchCollection
from matplotlib.patches import Polygon
from shapely.geometry import Point
import seaborn as sns
import numpy as np

# some pretend data
data = {'lat':[2.7,3.5,1.4,2.3,.9,1.9], 'lon':[1.2,.9,1.9,2.2,3,1.1]}
df = pd.DataFrame(data)

# the 'bounding' polygon
poly = box(1,1,2,2)
patches  = PatchCollection([Polygon(poly.exterior)], facecolor='red', linewidth=.5, alpha=.5)


# plot the bounding box 
fig, ax = sns.plt.subplots(1, figsize=(4,4))
ax.add_collection(patches, autolim=True)

# plot the lat/lon points
df.plot(x='lat',y='lon', kind='scatter',ax=ax)
plt.show()

这些数字看起来像这样:

enter image description here

摆脱不需要的点的一种方法是使用布尔掩码:

#probably more efficient ways to do this, but this works
mask = [poly.intersects(Point(lat,lon)) for lat,lon in zip(df.lat,df.lon)]
df = df[mask]

# make new plot (must make a new 'patch' object)
patches1  = PatchCollection([Polygon(poly.exterior)], facecolor='red', linewidth=.5, alpha=.5)
fig1, ax1 = sns.plt.subplots(1, figsize=(4,4))
ax1.add_collection(patches1, autolim=True)

# make the axis bounds the same
ax1.set_xlim(ax.get_xlim())
ax1.set_ylim(ax.get_ylim())

# plot the lat/lon points
df.plot(x='lat',y='lon', kind='scatter',ax=ax1)
plt.show()

给我这张照片。

enter image description here

请注意,您可以使用其他更快的方式制作布尔蒙版,例如lat是否高于多边形中的最高点。这些可能并不完美,但可以减少问题,因此您不必多次拨打intersects()

[编辑:如果您的多边形是一个矩形,]另一种方式(正如您在问题中所建议的那样)将只是“裁剪”。边界多边形周围的图像。这是一个更快的解决方案,因为您不必一遍又一遍地调用intersects()函数。要根据边界多边形修剪图像,可以在plt.plot()

之前插入此图像
ax.set_xlim((np.min(poly.exterior.xy[0]),np.max(poly.exterior.xy[0])) )
ax.set_ylim((np.min(poly.exterior.xy[1]),np.max(poly.exterior.xy[1])) )

给出以下内容:

enter image description here

答案 1 :(得分:0)

This tutorial似乎做你想做的事。它还利用了geopandas内置的Rtree空间索引来实现快速交叉查询。

spatial_index = gdf.sindex
possible_matches_index = list(spatial_index.intersection(polygon.bounds))
possible_matches = gdf.iloc[possible_matches_index]
precise_matches = possible_matches[possible_matches.intersects(polygon)]

然后它将多边形及其内部和外部的点绘制成不同的颜色,就像您想要的那样。