You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现点与多边形/多多边形的包含判断及数据关联

问题描述
  • 现有两个数据表:filtered_commerce 和 filtered_secteur
    • filtered_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 02:10:34