别再手动算面积了!用Shapely+GeoPandas轻松处理GeoJSON地理数据

张开发
2026/4/21 4:56:43 15 分钟阅读

分享文章

别再手动算面积了!用Shapely+GeoPandas轻松处理GeoJSON地理数据
别再手动算面积了用ShapelyGeoPandas轻松处理GeoJSON地理数据地理空间数据分析正成为城市规划、环境监测和商业决策的核心工具。想象一下当你拿到一份包含数百个行政区划边界的GeoJSON文件时手动计算每个区域的面积和周长几乎是不可能完成的任务。这正是Python生态中Shapely和GeoPandas这对黄金组合大显身手的场景。1. 环境配置与数据准备在开始之前我们需要搭建一个高效的地理数据处理环境。推荐使用conda创建专属环境因为地理空间库的依赖关系较为复杂conda create -n geo_env python3.9 conda activate geo_env conda install -c conda-forge geopandas shapely提示通过conda-forge渠道安装可以自动解决GEOS等底层依赖避免常见的编译错误准备示例数据时我们可以从Natural Earth下载免费的行政区划数据。这里以中国省级边界为例import geopandas as gpd # 下载并加载中国省级行政区划数据 china gpd.read_file(https://naciscdn.org/naturalearth/110m/cultural/ne_110m_admin_0_countries.zip) china china[china[NAME] China].explode(index_partsTrue) china.to_file(china_provinces.geojson, driverGeoJSON)这份数据包含MultiPolygon几何对象每个省份可能由多个不连续的多边形组成比如沿海岛屿。用GeoPandas打开后数据结构如下列名类型描述geometryMultiPolygon空间几何数据NAMEstr国家名称POP_ESTfloat人口估算GDP_MDfloatGDP数据2. 空间几何计算实战传统GIS软件需要点击多个菜单才能完成的基础计算在Shapely中只需一行代码。让我们计算各省份的面积和周长from shapely.geometry import MultiPolygon # 计算几何属性 china[area] china.geometry.area # 平方米 china[perimeter] china.geometry.length # 米 # 转换为更友好的单位 china[area_km2] china[area] / 1e6 china[perimeter_km] china[perimeter] / 1e3实际项目中常遇到的挑战是处理带孔洞的多边形如湖泊中的岛屿。Shapely能精准计算这类复杂形状# 示例处理包含孔洞的多边形 from shapely.geometry import Polygon # 外圈坐标逆时针和内圈坐标顺时针 lake_with_island Polygon( [(0, 0), (10, 0), (10, 10), (0, 10)], holes[[(2, 2), (8, 2), (8, 8), (2, 8)]] ) print(f总面积: {lake_with_island.area}) # 100-3664 print(f外周长: {lake_with_island.exterior.length}) # 40 print(f内周长: {sum(hole.length for hole in lake_with_island.interiors)}) # 243. 高级空间操作技巧当需要合并相邻区域或提取重叠部分时空间操作函数就派上用场了。以下是五个最常用的操作union合并多个几何体如合并相邻地块intersection获取几何体交集如计算重叠区域difference几何体差异如扣除保护区buffer创建缓冲区如生成辐射范围simplify简化几何形状减少数据量演示如何合并长江三角洲三省一市# 选取长三角地区 yangtze_delta china[china[NAME_CHN].isin([上海市,江苏省,浙江省,安徽省])] # 合并几何图形 delta_union yangtze_delta.geometry.unary_union # 计算合并后的总面积 print(f长三角总面积: {delta_union.area / 1e6:.2f} km²)注意unary_union会自动处理可能存在的重叠区域比简单叠加更精确4. 可视化与成果输出计算结果最终需要直观呈现。GeoPandas内置了基于matplotlib的绘图功能import matplotlib.pyplot as plt fig, ax plt.subplots(figsize(12, 8)) # 按面积大小着色 china.plot( axax, columnarea_km2, legendTrue, schemequantiles, cmapOrRd, edgecolorblack, linewidth0.3 ) # 添加标注 for idx, row in china.iterrows(): centroid row.geometry.centroid ax.text( centroid.x, centroid.y, f{row[area_km2]/1000:.1f}K, fontsize6, hacenter ) plt.title(中国各省面积分布(km²)) plt.savefig(china_area_map.png, dpi300, bbox_inchestight)输出成果不仅可以是图片还能生成交互式地图。使用folium库创建可缩放的网页地图import folium m folium.Map(location[35, 105], zoom_start4) folium.GeoJson( china, style_functionlambda x: { fillColor: #ff0000, color: #000000, weight: 0.5 }, tooltipfolium.GeoJsonTooltip(fields[NAME_CHN, area_km2]) ).add_to(m) m.save(china_interactive.html)5. 性能优化技巧处理全国或全球数据时性能成为关键考量。以下是提升效率的三种方法1. 空间索引加速查询from shapely.strtree import STRtree # 构建空间索引 tree STRtree(china.geometry) # 快速查找与上海相邻的省份 shanghai china[china[NAME_CHN] 上海市].geometry.iloc[0] neighbors [china.iloc[i] for i in tree.query(shanghai.buffer(1)) if i ! shanghai.index]2. 并行处理大型数据集from multiprocessing import Pool def calculate_attributes(geom): return {area: geom.area, perimeter: geom.length} with Pool(4) as p: results p.map(calculate_attributes, china.geometry)3. 使用Dask-GeoPandas处理超大数据import dask_geopandas as dgpd ddf dgpd.from_geopandas(china, npartitions4) ddf[area] ddf.geometry.area.compute() # 分布式计算在处理实际项目时我发现最耗时的往往不是计算本身而是几何数据的I/O操作。将大型GeoJSON转换为更高效的格式可以显著提升性能格式读取速度写入速度文件大小适用场景GeoJSON慢慢大兼容性要求高Shapefile中等中等中等传统GIS系统Parquet快快小大数据处理PostGIS极快极快数据库企业级应用

更多文章