如何在GeoPandas中为地图子区域分类点位?
为事件点位匹配所属子区域的实现方法
不用手动写循环,GeoPandas自带的**空间连接(spatial join)**就能高效解决这个问题,步骤如下:
1. 准备数据
假设你已经有两个数据集:
- 子区域GeoDataFrame(命名为
gdf_regions):包含子区域名称列(比如region_name)和多边形geometry列 - 事件DataFrame(命名为
df_events):包含点位的经度(lon)、纬度(lat)列
2. 将事件数据转为GeoDataFrame
先把普通的事件DataFrame转换成带空间信息的GeoDataFrame,指定坐标系要和子区域数据一致:
import geopandas as gpd from shapely.geometry import Point # 用坐标创建点几何列 df_events['geometry'] = gpd.points_from_xy(df_events['lon'], df_events['lat']) # 转为GeoDataFrame,设置坐标系(和gdf_regions的CRS保持一致,比如EPSG:4326) gdf_events = gpd.GeoDataFrame(df_events, crs=gdf_regions.crs)
3. 执行空间匹配
用gpd.sjoin()完成点位与子区域的匹配,默认会把每个点落在的子区域信息合并到事件数据中:
# 空间连接:匹配每个点所在的多边形 matched_data = gpd.sjoin(gdf_events, gdf_regions, how='left', predicate='within')
how='left':保留所有事件点位,即使没有匹配到子区域(会显示NaN)predicate='within':判断点是否在多边形内部,也可以根据需求用intersects(包含边界点)
4. 整理结果
匹配完成后,matched_data里会包含原事件数据的所有列,加上子区域的region_name(以及其他子区域属性列),你可以按需筛选列:
# 提取需要的列,比如原事件列+子区域名称 final_data = matched_data[['事件ID', 'lon', 'lat', 'region_name']]
注意事项
- 确保两个GeoDataFrame的坐标系(CRS)完全一致,否则匹配会出错
- 如果有点位落在多个子区域边界上,会生成多行匹配结果,可根据需求用
drop_duplicates()去重,或者调整predicate参数 - 空间连接比手动循环效率高得多,尤其是处理大数据集时
内容的提问来源于stack exchange,提问作者Abubakar Popoola
相关产品推荐
相关产品推荐

