如何修复地图中缩放后破损变形的散点式饼图?
散点饼图放大后破损的解决思路
问题背景
- 为每个国家绘制带统计数据的散点饼图,数据样本中除
geometry和size外的列均为饼图分类 - 基于现有方案实现了基础视觉效果,但放大后饼图出现破损,需满足出版物级画质要求

实现的正常散点饼图效果:
现有代码
import geopandas as gpd import numpy as np import shapely import matplotlib.pyplot as plt import math # 参考相关方案实现的饼图绘制工具函数 def draw_pie(dist, xpos, ypos, size, ax): # 计算饼图切片的累积占比 cumsum = np.cumsum(dist) cumsum = cumsum / cumsum[-1] pie = [0] + cumsum.tolist() size = math.sqrt(size) colors = ["blue", "red", "yellow", "pink", "purple", "black", "red", "yellow", "pink"] for i, (r1, r2) in enumerate(zip(pie[:-1], pie[1:])): angles = np.linspace(2 * np.pi * r1, 2 * np.pi * r2) x = [0] + np.cos(angles).tolist() y = [0] + np.sin(angles).tolist() xy = np.column_stack([x, y]) ax.scatter([xpos], [ypos], marker=xy, s=size, color=colors[i], alpha=1) return ax fig, ax = plt.subplots(figsize=(20,40)) for idx, row in sample.iterrows(): ax = draw_pie([row[cols].tolist()], row.geometry.x, row.geometry.y, row["size"], ax) cx.add_basemap(ax, crs=countries_centers.crs, source=cx.providers.OpenStreetMap.Mapnik)
问题现象
放大后饼图出现边缘破损、不连续的情况:
解决思路
- 提升角度采样密度:
np.linspace()默认仅生成50个采样点,放大后会因点数量不足导致边缘断裂。修改为np.linspace(2 * np.pi * r1, 2 * np.pi * r2, num=200)(可根据实际需求调整num值),增加切片的平滑度 - 替换为Patch矢量绘制:放弃散点自定义marker的方式,改用matplotlib的
Wedge类直接绘制扇形补丁,生成的矢量图形放大后无失真,更适配出版物需求,示例代码:def draw_pie(dist, xpos, ypos, size, ax): cumsum = np.cumsum(dist) cumsum = cumsum / cumsum[-1] pie = [0] + cumsum.tolist() radius = math.sqrt(size) / 100 # 根据实际size调整半径缩放比例 colors = ["blue", "red", "yellow", "pink", "purple", "black", "red", "yellow", "pink"] for i, (r1, r2) in enumerate(zip(pie[:-1], pie[1:])): wedge = plt.Wedge((xpos, ypos), radius, r1*360, r2*360, color=colors[i]) ax.add_patch(wedge) return ax - 导出矢量格式文件:保存图片时选择PDF、SVG等矢量格式,而非JPG/PNG位图,从根源上避免放大失真,示例:
plt.savefig('scatter_pie.pdf', dpi=300, bbox_inches='tight') - 优化尺寸缩放逻辑:当前
size = math.sqrt(size)的缩放可能导致小尺寸饼图的绘制精度不足,可调整缩放系数,确保小饼图也有足够的绘制细节
内容的提问来源于stack exchange,提问作者Jan Pisl
相关产品推荐
相关产品推荐

