如何用PIL/imageio获取网络国旗图片替换Matplotlib饼图文字标签
用国旗图片替换Matplotlib饼图的文字标签
Matplotlib的pie()方法不支持直接将图片作为标签,我们可以通过下载图片+在标签位置添加图片补丁的方式实现需求,以下是基于PIL/requests或imageio的完整解决方案:
依赖安装
如果使用PIL+requests:
pip install matplotlib pillow requests
如果使用imageio:
pip install matplotlib imageio
完整代码实现
方案1:使用PIL+requests加载网络图片
import matplotlib.pyplot as plt from PIL import Image import requests from matplotlib.offsetbox import OffsetImage, AnnotationBbox nationalities = { 'Fr': 5, 'De': 10, 'It': 3, 'Se': 5, 'Pl':2, 'Cz': 3, } flags = { 'Fr':'https://www.touteleurope.eu/wp-content/uploads/2022/08/drapeau-France.png', 'De':'https://www.touteleurope.eu/wp-content/uploads/2022/07/drapeau-allemagne.png', 'It':'https://www.touteleurope.eu/wp-content/uploads/2022/08/drapeau-Italie.png', 'Se':'https://www.touteleurope.eu/wp-content/uploads/2022/07/1280px-Flag_of_Sweden.svg.png', 'Pl':'https://www.touteleurope.eu/wp-content/uploads/2022/08/drapeau-Pologne.png', 'Cz':'https://www.touteleurope.eu/wp-content/uploads/2022/08/drapeau-Republique-tcheque.png', } # 从URL加载国旗图片 def load_flag(url): response = requests.get(url, stream=True) return Image.open(response.raw) fig, ax = plt.subplots(figsize=(18,6)) plt.xticks(fontsize=20) plt.yticks([], fontsize=20) composer_counts = list(nationalities.values()) country_codes = list(nationalities.keys()) # 绘制饼图,用空字符串占位标签,获取每个标签的位置对象 wedges, texts = plt.pie( composer_counts, labels=['']*len(composer_counts), radius=1, wedgeprops={'linewidth': 1.0, 'edgecolor': 'white'}, ) # 计算最大占比的百分比 max_percent = 100 * max(composer_counts) / sum(composer_counts) print(f"{int(max_percent)}%") # 为每个标签位置添加国旗图片 for text, code in zip(texts, country_codes): # 获取原文字标签的坐标 x, y = text.get_position() # 加载并调整图片大小 flag_img = load_flag(flags[code]) img_box = OffsetImage(flag_img, zoom=0.1) # zoom参数控制图片缩放比例 # 将图片绑定到坐标位置,关闭边框 ab = AnnotationBbox(img_box, (x, y), frameon=False) ax.add_artist(ab) # 添加中心百分比文本 plt.text(s=f"{int(max_percent)}%", x=-0.7, y=0.3, fontsize=30, color='white') plt.tight_layout() plt.show()
方案2:使用imageio加载网络图片
仅需替换图片加载函数,其余代码与方案1一致:
import imageio.v3 as iio # 从URL加载国旗图片 def load_flag(url): return iio.imread(url)
关键步骤说明
- 图片加载:通过requests/imageio从网络获取图片,PIL/imageio负责图片格式处理
- 饼图绘制:用空字符串占位标签,获取
texts对象以获取每个标签的坐标位置 - 图片嵌入:使用
OffsetImage将图片转为Matplotlib兼容对象,AnnotationBbox将图片绑定到对应坐标,zoom参数可调整图片大小适配饼图
内容的提问来源于stack exchange,提问作者RémyClaverie
相关产品推荐
相关产品推荐

