GeoPandas中两个GeoDataFrame相交无结果的技术求助
问题分析与修正方案
我帮你梳理下代码里的几个关键问题,这些应该就是导致相交分析没结果的核心原因:
几个关键错误点
- 变量名混乱:读取Excel时你用了
f = pd.read_excel(...),但后续创建点要素时却调用了未定义的df,变量名不统一会直接导致数据读取失败。 - 经纬度顺序颠倒:德语里
geoBreite是纬度(Latitude)、geoLaenge是经度(Longitude),而Shapely的Point要求参数顺序是**(经度, 纬度)**,你原来的顺序写反了,会导致所有点的位置完全错误。 - 缓冲区操作顺序错误:你的shapefile是UTM投影(单位为米),应该先在UTM坐标系下做缓冲(保证距离单位准确),再转换到WGS84。你现在先缓冲再转投影,相当于在经纬度坐标系下缓冲"100度",这完全不符合你要的千米级缓冲需求。
- 相交分析逻辑错误:
intersects按行一一对应判断相交,但你的点数据和多边形数据行数大概率不一致,应该用空间连接或空间索引来判断点是否在任意多边形内。 - 路径语法问题:Windows路径里的反斜杠需要用原始字符串(加
r前缀)避免转义错误,最后导出代码还缺闭合引号和括号。
修正后的完整代码
import pandas as pd import geopandas as gpd from shapely.geometry import Point # 1. 读取站点Excel数据,用原始字符串避免路径转义错误 df = pd.read_excel(io=r'C:\Users\peilj\meteo_sites.xlsx') # 2. 转换为GeoDataFrame:注意Point的顺序是(经度, 纬度) geometry = [Point(xy) for xy in zip(df.geoLaenge, df.geoBreite)] df = df.drop(['geoBreite', 'geoLaenge'], axis=1) # 用EPSG代码定义CRS更简洁可靠,WGS84对应EPSG:4326 crs = "EPSG:4326" gdf_points = gpd.GeoDataFrame(df, crs=crs, geometry=geometry) # 3. 读取多边形Shapefile并生成缓冲区 # 读取原始UTM投影的多边形数据 gdf_polygons = gpd.read_file(filename=r'C:\Users\peilj\lkr_vallanUTM.shp') # 在UTM坐标系下生成100千米缓冲区(UTM单位是米,100km=100000m) gdf_buffer = gpd.GeoDataFrame( geometry=gdf_polygons.buffer(100000), crs=gdf_polygons.crs ) # 将缓冲区转换为WGS84坐标系,和点数据保持一致 gdf_buffer = gdf_buffer.to_crs(crs) # 4. 空间相交分析:用空间连接高效判断点是否在缓冲区内 gdf_final = gpd.sjoin(gdf_points, gdf_buffer, how='left', predicate='intersects') # 标记相交状态:1表示在缓冲区内,0表示不在 gdf_final['intersection'] = gdf_final['index_right'].notna().astype(int) # 删除空间连接生成的临时列 gdf_final = gdf_final.drop('index_right', axis=1) # 5. 导出结果Shapefile gdf_final.to_file(driver='ESRI Shapefile', filename=r'C:\GIS\dwd_stationen.shp')
额外提示
如果数据量较大,推荐用空间索引提升相交判断效率,替代上面的空间连接代码:
# 创建缓冲区的空间索引 sindex = gdf_buffer.sindex # 遍历每个点,检查是否在任意缓冲多边形内 gdf_points['intersection'] = gdf_points.geometry.apply( lambda x: any(gdf_buffer.iloc[list(sindex.query(x))].geometry.contains(x)) ).astype(int) gdf_final = gdf_points
内容的提问来源于stack exchange,提问作者HappySpartan
相关产品推荐
相关产品推荐

