ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用Python绘制个性化世界地图:从入门到进阶

用Python绘制个性化世界地图:从入门到进阶 我用 Python 画过不少图从最基础的折线图、散点图到比较复杂的热力图都折腾过但要说哪一次最让身边朋友觉得“哇”的反而是那张看起来并不复杂的个性化世界地图。Python 绘图走进大众视野多半是从 matplotlib 的折线图开始的可当你把同样的思路放到地理数据上能做的事情就完全不一样了——你可以按国家填充颜色把自己的旅行足迹标记上去甚至把某个项目的全球站点分布直接可视化出来。这篇文章就围绕“用 Python 绘制一张只属于你自己的世界地图”这件事从环境搭建到数据准备、从最简单的地图底图到个性化的标注与配色把完整流程掰开揉碎讲清楚。不管你是刚接触 Python 的新手还是已经写过不少报表脚本的老手只要你想做一张不撞款的专属地图这篇内容都值得你花十几分钟读一读。先说明一点这个话题并不难难点从来不是代码量而是“你是否真的理解地理数据是怎么被画到屏幕上的”。理解了这一点后面所有操作都是一层窗户纸。1. 整体设计与思路拆解1.1 为什么选择用 Python 绘制世界地图很多人会问现在在线地图工具这么多拖拖拽拽就能生成一张世界地图为什么还要用 Python 自己画我的回答通常只有一个自由度。在线工具给你的是一套固定的模板你只能在它提供的样式里面选颜色、换字体一旦涉及到“把公司 200 个海外站点画成气泡图并且按业务线区分颜色”“把过去五年的旅行路线连成线段”“把某个指标按国家填色做成专题地图”在线工具的免费版本基本就捉襟见肘了。而 Python 不一样它把整张图的每一个像素都交给你控制底图、配色、标注、图例、投影方式全部可以按需定制。另外还有一个非常实际的原因可复现性。手动画图做完就没了但代码不一样只要把数据更新一下一键跑完又是一张新图。我最早做全球业务分布图的时候手动用设计软件画了一版当时觉得挺满意结果季度数据一更新整个人就傻眼了——所有国家的位置要重新调、颜色要重新配整整一下午耗在上面。后来我把这套流程搬到了 Python 里同样的图数据换一下重跑脚本五分钟搞定。这种效率提升是肉眼可见的。1.2 技术选型matplotlib、geopandas 与 cartopy 的分工做 Python 地图可视化业界的常规搭配是三个库协同工作matplotlib负责最终的绘图与样式控制是整张图的“画布”和“笔刷”。geopandas负责读取和处理地理空间数据可以把它理解成“支持地理数据的 pandas”DataFrame 里每一行都是一个带几何形状的记录。cartopy负责地图投影和坐标转换解决“地球是圆的屏幕是平的”这个核心矛盾。我用这个组合已经有很长时间了老实说最让新手困惑的就是第三个库——cartopy。很多人第一次画世界地图直接用 matplotlib 的 plot 或者 fill 把经纬度点连起来结果发现画出来的国家形状是变形的比如俄罗斯看着比实际还要扁那就是因为忽略了投影问题。cartopy 的价值就在于此它专门处理地理坐标到平面坐标的数学转换。除了这三个库还有一个已经没落的 basemap这里提醒大家不要用。basemap 是 matplotlib 的旧地图工具包官方早就停止维护了网上虽然还有大量教程在用但它跟新版 Python 的兼容性非常差装了容易报错遇到问题也找不到人帮你解决。新项目一律从 geopandas 加 cartopy 起步这才是现在社区的主流方案。提示如果你只是画一张简单的、示意性质的世界地图不涉及精确投影那么只装 matplotlib 和 geopandas 也够用。cartopy 是在你要切换投影方式、追求更“地图感”的效果时才必须引入的。1.3 整体流程框架五步走我习惯把整个项目拆成五个阶段理清这个框架之后再动手思路会非常清晰准备基础数据下载世界各国的边界数据通常用 Natural Earth 的公开数据集用 geopandas 读入内存。数据初探与清洗检查数据字段、处理缺失值、把不需要的区域剔除掉。绘制基础底图先用最简单的方式把世界地图画出来确保数据没问题。叠加个性化信息添加坐标点、连线、文字标注、按字段着色等。样式打磨与输出调整配色、图例、标题、分辨率导出最终图片。接下来我会按这个顺序一步步演示期间会把最容易踩坑的地方单独拎出来讲。2. 环境搭建与地理数据准备2.1 Python 环境安装与库依赖这一步看似基础但环境没配好后面全是泪。Python 的安装其实没什么玄学去官网下载对应操作系统的安装包安装时记得勾选“Add Python to PATH”这样后续在命令行直接敲python就能进入环境。装完之后打开终端或命令提示符输入python --version看看版本号是否正常输出。然后是安装第三方库。我推荐直接用 pip 一把梭pip install matplotlib geopandas pyproj如果还需要处理数据顺便把 pandas 也装上geopandas 会作为依赖自动安装但显式安装保证版本可控pip install pandas scipycartopy 我单独列出因为它在 Windows 上的安装偶尔会遇到一点波折。如果直接用 pip 安装失败建议去 Christoph Gohlke 维护的轮子页面下载对应的.whl文件再安装。不过现在新版 cartopy 的依赖已经简化了不少多数情况下直接pip install cartopy就能成功。装完之后用python -c import geopandas; import cartopy; print(ok)验证一下能打印出 ok 就说明环境没问题。注意别把 geopandas 和 cartopy 弄混。前者负责读取和处理地理数据后者负责投影转换。初学者经常以为装了一个就够用了结果画出图来才发现既没有地图数据也没有投影支持。2.2 世界地图边界数据从哪里来做地图可视化数据源的选择直接决定最终效果。我用得最多的是 Natural Earth 数据集这是一套完全免费、无需注册、可以直接商业使用的公开地理数据里面的国界、省界、河流、城市数据都很全而且更新稳定。Natural Earth 提供了几个尺度从 10m最精细文件大到 50m、110m最粗略文件小。画全球范围的地图时我一般选 110m 或者 50m 就够了如果拉伸到局部区域再考虑 10m。文件太大不仅下载慢后期绘图速度也会受影响。有两种方式获取数据。第一种是去 Natural Earth 官网手动下载ne_110m_admin_0_countries的 zip 包解压后你会得到一堆同名但后缀不同的文件。第二种更快直接用 geopandas 远程读取import geopandas as gpd url https://naturalearth.s3.amazonaws.com/110m/cultural/ne_110m_admin_0_countries.zip world gpd.read_file(url)这个操作会把整个国家边界数据集直接读进来不需要手动解压。第一次跑的时候会有一点下载时间之后就会缓存到本地。有一个细节值得注意读取出来的world其实就是一个 GeoDataFrame每一行代表一个国家里面有NAME国家名称、CONTINENT大洲、POP_EST人口估算等字段还有一个特殊的geometry列存储的是这个国家边界的 Polygon多边形或 MultiPolygon复合多边形。理解这一点非常关键因为后续所有“按国家填色”的操作本质都是基于这个geometry列来填充颜色的。2.3 了解 GeoDataFrame 的几何结构如果你接触过 pandas那么上手 GeoDataFrame 会非常轻松它就是 pandas 的扩展多了一个geometry列并且提供了很多空间操作方法。对于新手来说第一次拿到数据后应该先做两件事print(world.columns.tolist()) print(world[[NAME, CONTINENT, POP_EST]].head(10))看看有哪些列、数据长什么样。我还会顺手检查一下几何类型print(world.geom_type.value_counts())正常情况下你会看到大量Polygon和MultiPolygon。个别国家比如俄罗斯、美国、印尼是有多个不相连的多边形组成的 MultiPolygon这是地理上很正常的事情。理解这一点能避免你在后面自定义着色时遇到“为什么我的图上俄罗斯颜色不对”的疑惑。2.4 数据初体验把第一张地图画出来环境配好、数据读进来之后先用最简单的方式把地图画出来验证整条链路是否通畅import matplotlib.pyplot as plt fig, ax plt.subplots(figsize(15, 8)) world.plot(axax, color#f2efe9, edgecolor#333333, linewidth0.3) ax.set_aspect(equal) plt.show()这段代码会生成一张浅色底、深色边框的世界地图。color控制国家填充色edgecolor控制边界线颜色linewidth是边界线粗细。到这里你的第一张“世界地图”已经诞生了。虽然它还很素但底层的数据链路已经全部打通后面所有的进阶操作都是在这张底图之上做文章。我会在这里多强调一句先跑通最小版本再往上加东西。很多人一上来就想画一张完美的大图结果环境、数据、代码问题混在一起根本不知道从哪排查。3. 核心实操从空白底图到完整定制地图3.1 按大洲着色让地图一眼看懂基础底图画出来后第一步优化就是“填色”。填色有两个思路离散分类和连续渐变。最直观的是按大洲分类填色比如亚洲用一种颜色、欧洲用另一种颜色。geopandas 对这类操作支持得非常直接import matplotlib.pyplot as plt import geopandas as gpd url https://naturalearth.s3.amazonaws.com/110m/cultural/ne_110m_admin_0_countries.zip world gpd.read_file(url) fig, ax plt.subplots(figsize(15, 8)) world.plot( columnCONTINENT, axax, categoricalTrue, legendTrue, cmapSet3, edgecolorwhite, linewidth0.3 ) ax.set_aspect(equal) plt.show()这里面的核心参数是columnCONTINENT它告诉 geopandas“按这一列的取值来决定每个国家的填充颜色”。categoricalTrue表示按离散类别处理cmapSet3是 matplotlib 内置的配色方案legendTrue会自动在图上画一个图例框。跑完这段代码你会看到五个大洲分别以不同颜色呈现。这张图已经有点“作品感”了。但注意南极洲也在数据里它的 CONTINENT 字段是 Antarctica通常为了美观我们会把它过滤掉尤其是画深色背景的时候一大块浅色南极洲会破坏整体视觉world world[world[CONTINENT] ! Antarctica]用连续数值字段做填充也一样简单比如按人口POP_EST填色只要把categoricalTrue去掉指定一个连续色带world.plot(columnPOP_EST, axax, legendTrue, cmapYlOrRd, edgecolorwhite, linewidth0.3)两种方式各有各的适用场景。分类填色适合展示“定性”信息比如哪个国家属于哪个大洲、哪个地区属于哪个区域连续渐变适合展示“定量”信息比如人口、GDP、碳排放量。理解了categorical这个参数的本质区别你就能随意切换两种表达方式。3.2 把坐标点标上去你的地图坐标体系填色只是第一步真正让地图变得“只属于你自己”的是叠加个人坐标点。比如说我把自己去过的一些城市标在地图上一下子就做成了“旅行足迹图”。这里核心要理解的是坐标系。Natural Earth 数据默认的坐标系是 WGS84经纬度坐标系所以地图上的位置都是经度、纬度表示。你要标注一个城市只需要提供它的经纬度即可。比如北京东经 116.4074北纬 39.9042伦敦西经 0.1278北纬 51.5074纽约西经 74.0060北纬 40.7128把这些坐标点画到地图上最直接的方式是ax.scattercities_df gpd.GeoDataFrame( { name: [Beijing, London, New York], lon: [116.4074, -0.1278, -74.0060], lat: [39.9042, 51.5074, 40.7128], }, geometrygpd.points_from_xy([116.4074, -0.1278, -74.0060], [39.9042, 51.5074, 40.7128]) )然后用下面的方式叠加到现有地图上fig, ax plt.subplots(figsize(15, 8)) world.plot(axax, color#f2efe9, edgecolor#555555, linewidth0.3) cities_df.plot(axax, color#d62728, markersize60, alpha0.8) for x, y, name in zip(cities_df.lon, cities_df.lat, cities_df.name): ax.annotate(name, xy(x, y), xytext(5, 5), textcoordsoffset points, fontsize10) ax.set_aspect(equal) plt.show()关键是ax.scatter也可以直接用经纬度画点但用手动散点容易出现坐标系不匹配的问题。用geopandas的points_from_xy构造一个点 GeoDataFrame再plot叠加可以保证它和world在同一个坐标系下不会莫名其妙偏移。这一步是我在实际操作中被坑过一次之后总结出来的经验——理论上ax.scatter(cities_df.lon, cities_df.lat)也能显示但一旦后续更换了投影方式散点就会和地图分离。用 GeoDataFrame 叠加则能规避这个问题。3.3 给地图加标题、图例与坐标轴细节很多新手画图时容易忽略标题和图例的重要性但一张图的信息传达效率很大程度上取决于这些“装饰品”。这里我对标一下平时画折线图和散点图时用的那套逻辑matplotlib 里设置标题是ax.set_title设置坐标轴名称是ax.set_xlabel和ax.set_ylabel设置图例是ax.legend。世界地图本质还是一张 matplotlib 图所以这些接口全部适用。我习惯这样处理ax.set_title(My Personal World Map, fontsize18, pad20) ax.set_axis_off() # 去掉经纬度刻度线这里set_axis_off()值得多说两句。画数学图时我们喜欢坐标系和刻度线但画地图时经纬网格线通常显得多余除非你要做专业的 GIS 制图否则建议直接关掉让画面更干净。如果保留图例可以通过调整legend_kwds来控制图例的位置和样式。比如按大洲分类填色的时候world.plot( columnCONTINENT, axax, categoricalTrue, legendTrue, legend_kwds{loc: lower left, frameon: False, fontsize: 10}, cmapSet3, edgecolorwhite, linewidth0.3 )legend_kwds里的参数和 matplotlib 原生的图例参数一致后面所有对ax.legend()的定制都可以放进这个字典里。3.4 优化配色从“默认色”到“个人风格”说实话matplotlib 默认的配色在科研论文里还行但要是想发朋友圈或者做工作汇报观感会差一些。我探索过几套比较适合世界地图的配色方案第一种是“复古大地色系”。底图用米黄色边界线用深棕色。这个风格特别适合旅行足迹图看起来有一种旧地图的味道world.plot(axax, color#f5e6c8, edgecolor#8b7355, linewidth0.4) background_color #fdf6e3第二种是“深空风格”。底图用深色国家填充用暗色系点线用亮色。这种风格适合展示 SpaceX 星链轨迹、全球数据中心分布这类科技感强的数据fig.patch.set_facecolor(#1a1a2e) ax.set_facecolor(#1a1a2e) world.plot(axax, color#2d2d44, edgecolor#4a4a6a, linewidth0.3) cities_df.plot(axax, color#ffd166, markersize80, alpha0.95)第三种是“清爽商务风”。底图浅灰、国家白色、边界浅灰标注用品牌主色。这种风格最适合工作场景PPT 里放进去不抢眼但信息清晰world.plot(axax, colorwhite, edgecolor#cccccc, linewidth0.3) ax.set_facecolor(#f0f0f0)配色没有标准答案核心是“让背景弱下去、让主题跳出来”。我建议你至少准备两套配色模板一套浅色、一套深色根据使用场景灵活切换。3.5 点线面结合画出个人旅行路线光有离散的点还不够把点连成线你能得到更多信息。比如把你一年的旅行轨迹按时间顺序连起来就能看到自己这一年走了哪些地方、路线怎么规划的。用 matplotlib 的plot画线很简单但要画在地图上同样要注意坐标系匹配。我最常做的一种路线图是这样的# 按旅行顺序定义坐标点 route_lons [-74.0060, -0.1278, 116.4074, 139.6917] # 纽约 - 伦敦 - 北京 - 东京 route_lats [40.7128, 51.5074, 39.9042, 35.6762] fig, ax plt.subplots(figsize(15, 8)) world.plot(axax, color#f2efe9, edgecolor#cccccc, linewidth0.3) ax.scatter(route_lons, route_lats, color#d62728, s60, zorder5) ax.plot(route_lons, route_lats, color#d62728, linewidth1.5, alpha0.7, zorder4) ax.set_axis_off() plt.show()这里zorder参数很关键它的意思是“绘制顺序层级”数字越大越靠上。如果不设置线段可能会被国家多边形盖住或者压在底下观感很差。设置zorder5能保证点和线始终显示在地图之上。如果想做得更精细一点还可以让线段带一点弧线效果模拟真实航线的航路弯曲。这个操作稍微复杂一些需要手动在两点之间插值生成贝塞尔曲线点。如果你只是做展示我还教你一个小技巧给每条线段设置虚线样式代码只需要在plot里加一个linestyle--视觉上就有“规划路线”的感觉。4. 进阶玩法让地图从“能看”变成“惊艳”4.1 更换投影方式球面世界的另一种打开方式前面画的所有地图都是默认的等距圆柱投影也就是经纬度直接对应平面坐标效果类似于教科书上常见的那张长方形的世界地图。这种投影方式对中纬度地区的形状变形不大但到了高纬度比如格陵兰、俄罗斯就会显得特别大视觉比例和真实面积差距明显。要让地图更接近“真实”或者更有视觉冲击力可以引入 cartopy 更换投影方式。比如用正交投影地图会呈现出一个从太空中看到的球体效果import cartopy.crs as ccrs fig plt.figure(figsize(12, 12)) ax plt.axes(projectionccrs.Orthographic(central_longitude20, central_latitude30)) ax.add_geometries(world.geometry, crsccrs.PlateCarree(), facecolor#e0e0e0, edgecolor#666666, linewidth0.2) ax.set_global() plt.show()这里需要解释一个非常核心的概念crs。ccrs.PlateCarree()是经纬度坐标投影也就是我们数据的原始坐标系ccrs.Orthographic(...)是你要展示的目标投影。add_geometries里的crs参数告诉 cartopy“这些几何体原本是什么坐标系”cartopy 会帮你自动转换到目标投影上。这个自动转换能力是 cartopy 最方便的地方。如果你想在正交投影下叠加城市点只需要ax.scatter( [116.4074, -0.1278], [39.9042, 51.5074], transformccrs.PlateCarree(), colorred, s60 )注意这里的transformccrs.PlateCarree()它表示“这些散点数据本身的坐标系是经纬度”cartopy 会自动把它们转换到图的投影坐标系上。理解了crs和transform这两个参数cartopy 的核心就算入门了。Orthographic 投影特别适合做那种“地球悬浮在黑色太空”风格的效果。把背景设置成深色全球只画出部分国家配合亮色标记点做出来就像一张卫星轨迹图视觉效果极佳。4.2 数据气泡图让地图承载更多信息地图不只是看位置的它更是一个承载信息的面板。平时我们用散点图展示两个变量的关系在 GIS 领域里可以在世界地图上做“气泡图”——把另一个维度的信息编码成点的大小或颜色叠加在地图上。一个典型的应用场景是展示你关注的网站或 APP 全球用户分布。每个城市一个点点的面积大小对应用户量。代码实现并不复杂import numpy as np # 假设有一些城市数据城市名、经度、纬度、用户量 city_data { names: [Beijing, London, New York, Tokyo, Sydney], lons: [116.4074, -0.1278, -74.0060, 139.6917, 151.2093], lats: [39.9042, 51.5074, 40.7128, 35.6762, -33.8688], users: [1200, 800, 1500, 600, 300] } fig, ax plt.subplots(figsize(15, 8)) world.plot(axax, color#f2efe9, edgecolor#cccccc, linewidth0.3) # 用用户量映射气泡尺寸 sizes np.array(city_data[users]) / np.max(city_data[users]) * 1500 ax.scatter(city_data[lons], city_data[lats], ssizes, alpha0.6, color#1f77b4, edgecolorwhite, linewidth1, zorder5) ax.set_axis_off() plt.show()np.array归一化尺寸这一步是核心。把数据数值映射到图上面积的时候一定先归一化到合理范围不然数值相差太大的话大点会糊成一片小点则看不见。alpha0.6和白色描边是为了让重叠的点更有层次感。如果你想再加一层信息还可以用颜色编码第三个变量。比如蓝色代表用户量、红色代表付费用户占比这就是地图单变量展示升级到多变量展示的常见方式。4.3 合并外部数据让地图和你的业务数据联动前面用的都是 Natural Earth 自带的国家属性数据但实际工作中你通常需要把自己的业务数据和地理数据合并到一张表里才能画出一张有业务含义的地图。假设你有一份 CSV记录了各个国家的销售业绩import pandas as pd sales pd.read_csv(sales_by_country.csv) # 假设字段为country, sales # country 是国家的英文名称sales 是销售额接下来用国家名称作为关联键合并进地理数据world gpd.read_file(url) merged world.merge(sales, left_onNAME, right_oncountry, howleft)合并之后merged就多了一列sales。然后就可以按sales连续填色做一张“销售热力世界地图”fig, ax plt.subplots(figsize(15, 8)) merged.plot(columnsales, axax, legendTrue, cmapBlues, edgecolorwhite, linewidth0.3, legend_kwds{label: Sales by Country}) ax.set_axis_off() plt.show()这里howleft是关键它表示“以世界地图的国家列表为基准把销售数据补充进来”这样即使有些国家没有数据也不会丢国家。合并后再画图缺失数据的国家就会自动填充成NaN在图例中一般会显示为灰色或者不显示这取决于配色方案。实际操作中最容易翻车的点是国家名称对不上。Natural Earth 的国名标准和很多企业的本地化叫法对不齐比如“United States of America”和“USA”“United States”都指同一个国家。我的经验是第一步先用print(set(world[NAME]) - set(sales[country]))把对不上的国家名找出来再做一层手工映射否则合并完你会发现一大堆国家是灰的图根本没法看。4.4 局部区域放大当世界地图太长只看某个区域有时候真正的业务焦点只在一个区域比如东南亚、欧洲、或是东亚这时候画一张完整的世界地图反而分散注意力不如把局部区域放大展示。geopandas 里做区域裁剪非常简单直接用边界框过滤# 只看欧洲区域经度 -25 到 40纬度 35 到 70 europe world.cx[-25:40, 35:70]cx是 geopandas 提供的一个坐标切片方法按经纬度范围快速筛选几何对象。之后用europe画图就行fig, ax plt.subplots(figsize(12, 8)) europe.plot(axax, columnPOP_EST, cmapYlOrRd, edgecolorwhite, linewidth0.3, legendTrue) ax.set_axis_off() plt.show()区域裁剪配合局部数据标注在商务汇报里非常实用。比如你公司的主战场在东南亚六国那么你就没必要把整个亚洲都画出来只画东南亚反而更能凸显“聚焦”的意图。4.5 进阶小技巧让标记点与地图联动如果要把城市点标注得很漂亮我建议你别直接用 matplotlib 默认的散点可以考虑用ax.annotate给每个点加一个带箭头的标注。这样人多的地图上也不会挤作一团ax.scatter(lon, lat, s80, color#e74c3c, edgecolorwhite, linewidth1.5, zorder5) ax.annotate( Beijing, xy(lon, lat), xytext(lon 2, lat 2), fontsize10, arrowpropsdict(arrowstyle-, colorgray, lw0.8) )xytext控制文字相对于点的偏移量arrowprops控制箭头的样式。标注数量不多的时候这种方法是锦上添花标注很多的时候反而会显得杂乱建议只用它来标注最重要的几个点。5. 常见问题与排查技巧实录5.1 地图读取失败GeoJSON 还是 Shapefile新手经常遇到的一个问题是下载了数据解压后不知道该读哪个文件。Shapefile 是一类数据格式的总称它由多个同名文件组成例如.shp、.shx、.dbf、.prj。用 geopandas 读取时只需要指向.shp文件即可read_file会自己处理其余配套文件。如果你拿到的是.geojson文件同样用gpd.read_file(xxx.geojson)就能读。GeoJSON 是单文件格式不需要配套文件适合交换和分享。如果出现DriverError或提示文件不存在第一检查路径中是否包含中文或空格这是新手最容易犯的错误第二检查文件是否解压完整缺了.shx或者.dbf都会导致读取失败。5.2 绘制城市点时位置偏移城市点偏移通常是坐标系混用造成的。最典型的情况是底图用的是天然地球的经纬度坐标系但你手动把散点的lon、lat当成了平面直角坐标直接使用。在默认的等距圆柱投影下经纬度的数值大小差不多能对应屏幕位置所以一般不会出太离谱的问题但一旦切换成其他投影比如墨卡托或正弦曲线投影点的位置就会和地图完全对不上。解决办法就是前面强调过的要么始终使用ax.scatter(x, y, transformccrs.PlateCarree())并配合 cartopy 投影轴要么把所有散点都放在一个 GeoDataFrame 里然后统一叠加plot。5.3 地图染色出现“锯齿”或多边形重叠GeoDataFrame 里某些国家的几何边界可能是不完美的例如存在自相交的多边形、无效几何。直接绘图时这些地方会出现染色异常或者锯齿。在绘图之前先统一修复几何world[geometry] world[geometry].buffer(0).buffer(0)是一个很经典的 GIS 小技巧它可以修复很多无效几何问题。这个操作不会改变地图的视觉形状但能解决大量多边形重叠、自相交的问题。如果修复之后仍有部分区域染色不正常可以再看看是不是几何类型是 MultiPolygon 而数据格式有误。用world.geom_type.value_counts()确认一下一般都能发现问题。5.4 中文标签显示成方框matplotlib 对中文字体的支持一直是个老问题默认字体里不包含中文字体遇到中文直接显示成一个个方框。解决方案是手动指定中文字体import matplotlib matplotlib.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] matplotlib.rcParams[axes.unicode_minus] False第一行指定系统里已有的中文字体名第二行解决坐标轴负号显示为方块的问题。不同操作系统里可用的字体名称不一样Windows 通常是SimHei或Microsoft YaHeimacOS 是PingFang SC或Arial Unicode MSLinux 则要先确认是否安装了wqy-microhei之类的字体。5.5 图片导出模糊或到处有白边保存图片时用dpi参数控制清晰度fig.savefig(world_map.png, dpi300, bbox_inchestight)dpi300适合打印和为 PPT 准备。如果图片四周有大片空白加上bbox_inchestight会自动裁剪到内容边缘。如果导出的是矢量图可以保存成 PDF 或 SVG 格式缩放不模糊适合后续排版。5.6 常见问题速查表现象可能原因解决方案读取 .shp 文件报错路径中含中文或空格缺少配套文件去除路径特殊字符确认同目录下.shx.dbf文件存在地图上点位置偏移坐标系混用底图和散点坐标系不一致统一使用 GeoDataFrame 叠加或使用transform参数指定坐标系国家无法填充颜色几何对象无效或存在 NaN 值检查数据并使用buffer(0)修复几何中文变方框matplotlib 默认字体不支持中文配置rcParams[font.sans-serif]指定中文字体导出模糊保存时未指定 dpi使用dpi300绘图缓慢卡顿数据尺度过大或绘图对象过多使用 110m 或 50m 尺度数据避免 10m 全图标绘写在最后的几点实际操作体会折腾 Python 绘制世界地图这么久我自己最大的心得是地图可视化真正难的部分永远不是代码而是数据准备。你在网上看到的那些惊艳作品背后往往花了很多时间处理国名匹配、坐标转换、缺失值修补这类“不性感”的工作。但只要熬过这个阶段代码的灵活性会给你极大的正反馈——同一套脚本换一换数据就能出一张全新的图这种效率和自由度是用在线工具完全无法体会的。另外先用最快的方式把最丑的版本画出来再一点点加细节这是我做所有可视化项目的习惯。第一版丑没关系链路通了就成功了一半。如果你的目标是做一张能给工作汇报加分的彩色地图我的建议是把 80% 的时间花在配色、标注和整体视觉平衡上而不是纠结某个细节代码怎么写。这篇文章里用到的数据、代码思路基本覆盖了“用 Python 绘制一张专属世界地图”的核心环节从环境搭建、数据读取到填色、加标记、换投影、合并业务数据。后面你可以继续扩展的方向也很多比如结合 Folium 做交互式 HTML 地图、用 Cartopy 叠加气象遥感数据、甚至通过 Basemap 之外的其他库做三维地球展示。画地图这件事边界不只是那张图更在于你的想象。
返回列表