Python 如何有效地从geopandas df中过滤不在形状多边形边界内的行?

Python 如何有效地从geopandas df中过滤不在形状多边形边界内的行?,python,pandas,geospatial,geopandas,shapely,Python,Pandas,Geospatial,Geopandas,Shapely,我有一个常规的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)) 我还有一个坐标列表,我将其转换为一个形状良好的多边形,如下所示:

我有一个常规的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
中不在shapely polygon
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.GeopataFrame(输入_df,几何体=geopandas.points_自_xy(输入_df.经度,输入_df.纬度)
geo_-df_filtered=geo_-df.loc[geo_-df.in(网格多边形)]
但是,根据您拥有的数据类型和使用模式,有几种技术可以加快速度:

使用准备好的几何图形 如果多边形非常复杂,创建多边形将加快包容检查。 这将在开始时预先计算各种数据结构,从而加快后续操作。 (更多详情。)

来自shapely.prepared导入准备
网格\多边形\准备=准备(网格\多边形)
geo_df_filtered=geo_df.loc[geo_df.geometry.apply(lambda p:grid_polygon_prep.contains(p))]
(不能像上面那样执行
geo_df.loc[geo_df.in.(网格多边形准备)]
,因为geopandas不支持此处准备的几何图形。)

使用空间索引 如果需要针对多个而不是一个
grid\u polygon
s对给定的一组点运行包容检查,那么在这些点上使用空间索引是有意义的。 这将大大加快速度,特别是当分数很多的时候

Geopandas规定:

match\u index=geo\u df.sindex.query(grid\u polygon,predicate=“contains”)
#请注意,在这里使用'iloc'而不是'loc'很重要
geo_df_filtered=geo_df.iloc[匹配索引]

很好的博客文章,还有一些解释:

使用
geo_df.apply()
应该比for循环稍微快一点,但是除非
构造函数/检查可以矢量化,否则您必须迭代所有行。谢谢-是的,应用是一个选项,但我认为有一种更自然的方法可以做到这一点-我相信这里的强制转换实际上没有必要-必要的信息应该已经是e在geopandas df的init中由点_从_xy编码。我目前正在尝试使用逻辑df[df.geometry.within(polygon)],但仍在测试。这有帮助吗?