Python 绘制世界地图:从基础投影到高级地理特征定制

Python 绘制世界地图:从基础投影到高级地理特征定制 1. 为什么用Python画地图第一次接触地理数据可视化时我也觉得用专业GIS软件更靠谱。但实际工作中发现Python的CartopyMatplotlib组合简直是数据科学家的福音。比如上周我需要快速比对太平洋沿岸20个气象站的数据分布从导入数据到生成带地形底图的可视化报告用Python只花了15分钟。传统GIS软件虽然功能强大但Python的优势在于自动化流程可以嵌入数据处理流水线高度定制化每个地图元素的颜色、透明度都能精确控制生态丰富配合Pandas处理数据用Seaborn增强统计图表最让我惊喜的是Cartopy自带的110m精度自然地球数据集包含海岸线、国界、河流等基础地理要素完全能满足科研和商业分析的需求。下面这张基础世界地图用5行代码就能生成import cartopy.crs as ccrs import matplotlib.pyplot as plt fig plt.figure(figsize(12, 6)) ax fig.add_subplot(projectionccrs.PlateCarree()) ax.coastlines() plt.show()2. 地图投影的魔法选择刚开始用PlateCarree投影等距圆柱投影时我纳闷为什么格陵兰岛看起来比非洲还大。后来才明白这就像把橘子皮强行压平——必然会产生变形。Cartopy支持30种投影方式这里分享几个常用场景2.1 全球展示优选Robinson投影联合国常用适合展示全球统计数据ax fig.add_subplot(projectionccrs.Robinson())InterruptedGoodeHomolosine大陆形状更准确海洋会被切断2.2 区域分析必备兰伯特等角圆锥投影中纬度地区精度最高central_lon, central_lat 105, 35 # 中国中心坐标 ax fig.add_subplot(projectionccrs.LambertConformal( central_longitudecentral_lon, central_latitudecentral_lat))2.3 炫酷视觉效果Orthographic投影模拟太空视角ax fig.add_subplot(projectionccrs.Orthographic( central_longitude116.4, # 北京经度 central_latitude39.9)) # 北京纬度实测发现投影中心点坐标对区域地图影响巨大。有次我把中心点设错5度导致东亚海岸线严重畸变。建议先用set_extent限定显示范围ax.set_extent([70, 140, 15, 55]) # 东经70-140°北纬15-55°3. 让地图会说话的地理特征Cartopy的feature模块藏着不少宝藏。有次我绘制台风路径图用这些技巧让图表瞬间专业起来3.1 基础要素组合拳import cartopy.feature as cfeature ax.add_feature(cfeature.LAND, facecolor#DDDDDD) # 灰色陆地 ax.add_feature(cfeature.OCEAN, facecolor#EEEEFF) # 浅蓝海洋 ax.add_feature(cfeature.BORDERS, linestyle:) # 虚线国界 ax.add_feature(cfeature.RIVERS, edgecolorblue) # 蓝色河流3.2 高级定制技巧分辨率切换默认110m不够用时states cfeature.NaturalEarthFeature( categorycultural, nameadmin_1_states_provinces, scale50m) # 改用50m精度 ax.add_feature(states, edgecolorgray)自定义样式给长江特别标注rivers_50m cfeature.NaturalEarthFeature( physical, rivers_lake_centerlines, 50m) ax.add_feature(rivers_50m, edgecolorblue, linewidth1.5, linestyle-)3.3 实用小功能网格线标签经度纬度显示控制gl ax.gridlines(draw_labelsTrue, x_inlineFalse, y_inlineTrue) gl.top_labels False # 隐藏顶部标签 gl.right_labels False # 隐藏右侧标签地形底图快速添加地势效果ax.stock_img() # 使用内置地形图 # 或使用NASA的Blue Marble ax.background_img(nameBM, resolutionlow)4. 实战新冠疫情数据地图去年分析全球疫情时我结合Pandas和Cartopy做了个动态可视化。关键步骤包括数据准备import pandas as pd df pd.read_csv(covid_data.csv)创建带分级色彩的地图from matplotlib.colors import Normalize norm Normalize(vmin0, vmaxdf[cases].max()) for country in df.itertuples(): ax.plot(country.lon, country.lat, o, colorplt.cm.Reds(norm(country.cases)), transformccrs.PlateCarree(), markersizecountry.cases/1e5)添加图例和标题sm plt.cm.ScalarMappable(normnorm, cmapReds) plt.colorbar(sm, label确诊病例数) ax.set_title(2020年全球新冠疫情分布, pad20)输出高清图片plt.savefig(covid_map.png, dpi300, bbox_inchestight, facecolorwhite)遇到的一个坑是当数据点跨越国际日期变更线时会出现奇怪的直线。解决方法是用PlateCarree投影时设置central_longitude180。5. 性能优化技巧当处理高精度地理数据时我总结出这些提速方法矢量数据简化50m分辨率数据比10m快8倍coastline cfeature.NaturalEarthFeature( physical, coastline, 50m)栅格数据分块大数据集用imshow分块加载img ax.imshow(data, transformccrs.PlateCarree(), extent[-180,180,-90,90], originupper)多进程渲染对于全球1km网格数据from multiprocessing import Pool def render_chunk(args): # 分块渲染逻辑 pass with Pool(4) as p: p.map(render_chunk, chunks)记得有次渲染全球夜间灯光数据没优化前耗时27分钟调整后只需3分钟。关键参数是rasterizedTruescatter ax.scatter(x, y, cvalues, transformccrs.PlateCarree(), rasterizedTrue) # 矢量转栅格6. 常见问题解决方案坐标系混乱是最常遇到的问题。有次我的数据点在非洲上空飘着检查发现是忘了设置transform参数# 错误示范 ax.plot(lon, lat, ro) # 正确做法 ax.plot(lon, lat, ro, transformccrs.PlateCarree())其他实用技巧中文标注显示需要指定支持中文的字体plt.rcParams[font.sans-serif] [SimHei] ax.set_title(中国各省GDP分布)跨半球地图调整central_longitudeproj ccrs.PlateCarree(central_longitude180) ax fig.add_subplot(projectionproj)保存透明背景用于报告插图plt.savefig(map.png, transparentTrue, dpi300)最近帮同事调试时发现当使用非PlateCarree投影时必须先设置extent再添加要素否则会显示异常。这个顺序问题坑了不少人。