如何有效地过滤不在形状多边形边界内的 geopandas df 行?
How to efficiently filter rows from geopandas df that are not within the bounds of a shapely polygon?
我有一个常规 pandas 数据框,我像这样一次性转换为 geopandas
from shapely.geometry import Polygon, Point
import geopandas
geo_df = geopandas.GeoDataFrame(input_df, geometry=geopandas.points_from_xy(input_df.Longitude, input_df.Latitude))
我还有一个坐标列表,可以像这样转换成形状多边形:
grid_polygon = Polygon(shape_coordinates)
然后我想过滤 geo_df
中不在形状多边形 grid_polygon
范围内的所有行。
我目前的方法是:
geo_df['withinPolygon'] = ""
withinQlist = []
for lon,lat in zip(geo_df['longitude'], geo_df['latitude']):
pt = Point(lon, lat)
withinQ = pt.within(grid_polygon)
withinQlist.append(withinQ)
geo_df['withinPolygon'] = withinQlist
geo_df = geo_df[geo_df.withinPolygon==True]
但这效率很低。我认为有一种方法可以在不遍历每一行的情况下执行此操作,但是我能够找到的大多数解决方案都不会使用形状多边形进行过滤。有什么想法吗?
谢谢
作为第一步,正如您在评论中提到的,您的代码可以像这样简化:
import geopandas
geo_df = geopandas.GeoDataFrame(input_df, geometry=geopandas.points_from_xy(input_df.Longitude, input_df.Latitude)
geo_df_filtered = geo_df.loc[geo_df.within(grid_polygon)]
但是有一些技术可以加快速度,具体取决于您拥有的数据类型和使用模式:
使用准备好的几何图形
如果您的多边形非常复杂,创建 prepared geometry 将加快包含检查。
这样一开始就预计算了各种数据结构,加快了后续的运算速度。
(更多详情 here。)
from shapely.prepared import prep
grid_polygon_prep = prep(grid_polygon)
geo_df_filtered = geo_df.loc[geo_df.geometry.apply(lambda p: grid_polygon_prep.contains(p))]
(不能像上面那样做 geo_df.loc[geo_df.within(grid_polygon_prep)]
,因为 geopandas 不支持这里准备好的几何图形。)
使用空间索引
如果您需要 运行 针对许多 grid_polygon
点对一组给定的点进行包含检查,而不仅仅是一个点,那么在这些点上使用空间索引是有意义的。
它会显着加快速度,尤其是当有很多点时。
Geopandas 为此提供 GeoDataFrame.sindex.query
:
match_indices = geo_df.sindex.query(grid_polygon, predicate="contains")
# note that using `iloc` instead of `loc` is important here
geo_df_filtered = geo_df.iloc[match_indices]
不错的博文,还有更多解释:https://geoffboeing.com/2016/10/r-tree-spatial-index-python/
我有一个常规 pandas 数据框,我像这样一次性转换为 geopandas
from shapely.geometry import Polygon, Point
import geopandas
geo_df = geopandas.GeoDataFrame(input_df, geometry=geopandas.points_from_xy(input_df.Longitude, input_df.Latitude))
我还有一个坐标列表,可以像这样转换成形状多边形:
grid_polygon = Polygon(shape_coordinates)
然后我想过滤 geo_df
中不在形状多边形 grid_polygon
范围内的所有行。
我目前的方法是:
geo_df['withinPolygon'] = ""
withinQlist = []
for lon,lat in zip(geo_df['longitude'], geo_df['latitude']):
pt = Point(lon, lat)
withinQ = pt.within(grid_polygon)
withinQlist.append(withinQ)
geo_df['withinPolygon'] = withinQlist
geo_df = geo_df[geo_df.withinPolygon==True]
但这效率很低。我认为有一种方法可以在不遍历每一行的情况下执行此操作,但是我能够找到的大多数解决方案都不会使用形状多边形进行过滤。有什么想法吗?
谢谢
作为第一步,正如您在评论中提到的,您的代码可以像这样简化:
import geopandas
geo_df = geopandas.GeoDataFrame(input_df, geometry=geopandas.points_from_xy(input_df.Longitude, input_df.Latitude)
geo_df_filtered = geo_df.loc[geo_df.within(grid_polygon)]
但是有一些技术可以加快速度,具体取决于您拥有的数据类型和使用模式:
使用准备好的几何图形
如果您的多边形非常复杂,创建 prepared geometry 将加快包含检查。 这样一开始就预计算了各种数据结构,加快了后续的运算速度。 (更多详情 here。)
from shapely.prepared import prep
grid_polygon_prep = prep(grid_polygon)
geo_df_filtered = geo_df.loc[geo_df.geometry.apply(lambda p: grid_polygon_prep.contains(p))]
(不能像上面那样做 geo_df.loc[geo_df.within(grid_polygon_prep)]
,因为 geopandas 不支持这里准备好的几何图形。)
使用空间索引
如果您需要 运行 针对许多 grid_polygon
点对一组给定的点进行包含检查,而不仅仅是一个点,那么在这些点上使用空间索引是有意义的。
它会显着加快速度,尤其是当有很多点时。
Geopandas 为此提供 GeoDataFrame.sindex.query
:
match_indices = geo_df.sindex.query(grid_polygon, predicate="contains")
# note that using `iloc` instead of `loc` is important here
geo_df_filtered = geo_df.iloc[match_indices]
不错的博文,还有更多解释:https://geoffboeing.com/2016/10/r-tree-spatial-index-python/