Python实现点与多边形/多多边形的包含判断及数据关联
问题描述
- 现有两个数据表:
filtered_commerce和filtered_secteurfiltered_commerce的zone_population列存储 POLYGON/MULTIPOLYGON 类型的地理区域多边形filtered_secteur的centroid_degres列存储 POINT 类型的点数据,INS9列为点的唯一标识
- 需求:找出每个地理区域包含的点,将对应点的
INS9值存入filtered_commerce的新列中
尝试了以下代码,但没有区域匹配到任何点,zone.contains(point) 逻辑从未触发:
# Fonction pour trouver les INS9 des points dans chaque zone def find_points_in_zones(df_commerce, df_secteur): results = {} for commerce_index, row_commerce in df_commerce.iterrows(): zone = row_commerce['zone_population'] print(f"Zone {commerce_index}: {zone}") points_in_zone = [] for secteur_index, row_secteur in df_secteur.iterrows(): point = row_secteur['centroid_degres'] print(f" Point {secteur_index}: {point}") if zone.contains(point): print('il y a un point!') points_in_zone.append(row_secteur['INS9']) results[commerce_index] = points_in_zone return results points_in_zones = find_points_in_zones(filtered_commerce, filtered_secteur) # Afficher les résultats for zone_index, points in points_in_zones.items(): print(f"Zone {zone_index}: {points}")
此前项目另一部分使用类似逻辑可正常工作,但此处无效:
polygone_concurrence = isochrone_commerce_double.iloc[0]['geometry'] filtered_commerce.at[index, 'zone_concurrence'] = polygone_concurrence concurrents = filtered_commerce[filtered_commerce.geometry.within(polygone_concurrence)] concurrents_ids = concurrents['UNITID'].tolist() filtered_commerce.at[index, 'concurrence'] = concurrents_ids
可能的原因与解决办法
1. 坐标系不匹配(最常见原因)
检查两个表的几何列是否使用同一坐标系:
- 打印
zone.crs和point.crs确认坐标系是否一致 - 若不一致,将其中一个转换为另一个的坐标系,示例:
# 将filtered_secteur的点坐标系统一为filtered_commerce的坐标系 df_secteur['centroid_degres'] = df_secteur['centroid_degres'].to_crs(df_commerce['zone_population'].crs)
2. 几何对象有效性问题
多边形或点可能存在无效几何(如自相交多边形),导致空间判断失效:
- 验证并修复几何对象:
# 修复filtered_commerce中的无效多边形 df_commerce['zone_population'] = df_commerce['zone_population'].make_valid() # 修复filtered_secteur中的无效点 df_secteur['centroid_degres'] = df_secteur['centroid_degres'].make_valid()
3. 改用高效的空间连接替代循环
双重循环效率极低且易出错,建议使用geopandas的空间连接功能:
import geopandas as gpd # 转为GeoDataFrame(若尚未转换) gdf_commerce = gpd.GeoDataFrame(filtered_commerce, geometry='zone_population') gdf_secteur = gpd.GeoDataFrame(filtered_secteur, geometry='centroid_degres') # 空间连接:匹配多边形包含的点 joined = gpd.sjoin(gdf_commerce, gdf_secteur, how='left', predicate='contains') # 按多边形分组,聚合INS9为列表 result = joined.groupby(joined.index)['INS9'].apply(list).reset_index(name='INS9_points') # 合并回原表 filtered_commerce = filtered_commerce.merge(result, left_index=True, right_index=True)
4. 检查contains与within的逻辑差异
此前有效代码使用within(点在多边形内),当前代码使用contains(多边形包含点),逻辑互逆但几何异常时可能结果不同,可尝试替换:
# 替换原判断逻辑 if point.within(zone): points_in_zone.append(row_secteur['INS9'])
内容的提问来源于stack exchange,提问作者lsn
相关产品推荐
相关产品推荐

