如何修改Matplotlib代码将15个独立饼图合并为单图子图?
解决Matplotlib子图饼图绘制的AttributeError问题
你遇到的AttributeError: 'numpy.ndarray' object has no attribute 'pie'是因为当用plt.subplots(5, 3)创建子图时,返回的ax是一个5×3的NumPy数组,而非单个坐标轴对象,直接调用ax.pie()自然会报错。
下面是修改后的完整代码,实现将15个饼图合并为一张5行3列的子图:
import pandas as pd import matplotlib.pyplot as plt df = pd.read_excel(path) df_1 = df.groupby(['Site', 'group'])['Abundance'].sum().reset_index(name='site_count') site = ['Ireland', 'England', 'France', 'Scotland', 'Italy', 'Spain', 'Croatia', 'Sweden', 'Denmark', 'Germany', 'Belgium', 'Austria', 'Poland', 'Stearman', 'Hungary'] # 创建5行3列的子图画布,调整figsize避免子图拥挤 fig, axs = plt.subplots(5, 3, figsize=(18, 20)) # 将二维子图数组展平为一维,方便循环遍历 axs = axs.flatten() colors = {'Dog': 'orange', 'Cat': 'cyan', 'Pig': 'darkred', 'Horse': 'lightcoral', 'Bird': 'grey', 'Rat': 'lightsteelblue', 'Whale': 'teal', 'Fish': 'plum', 'Shark': 'darkgreen'} wp = {'linewidth': 1, 'edgecolor': "black"} # 同时遍历站点列表和对应的子图坐标轴 for idx, i in enumerate(site): df_1b = df_1.loc[df_1['Site'] == i] # 获取当前站点的group标签(修复原代码中labels未定义的问题) labels = df_1b['group'] # 使用展平后的子图坐标轴绘制饼图 texts, autotexts = axs[idx].pie(df_1b['site_count'], labels=None, shadow=False, colors=[colors[key] for key in labels], startangle=90, wedgeprops=wp, textprops=dict(color="black")) plt.setp(autotexts, size=10) # 调整文本大小适配子图 axs[idx].set_title(i, size=12, weight="bold", y=-0.1) # 标题改为当前站点,调整位置避免遮挡 # 调整子图间距,避免重叠 plt.tight_layout() # 保存整张合并后的图 plt.savefig('all_sites_group_diversity.png', bbox_inches='tight', pad_inches=0.05, dpi=600) plt.close()
关键修改点说明:
- 将子图创建代码移出循环,通过
axs.flatten()把二维坐标轴数组转为一维,方便循环调用 - 循环时通过
enumerate获取子图索引,对应到axs[idx]单个坐标轴对象 - 修复原代码中
labels未定义的问题,改为从df_1b['group']获取类别标签 - 调整标题文本、饼图文本的大小和位置,适配子图布局
- 最后统一保存整张图,而非逐个保存单独饼图
内容的提问来源于stack exchange,提问作者Orla Osborne
相关产品推荐
相关产品推荐

