Matplotlib添加子图后无法保存图像问题求助
问题排查:Matplotlib绘图保存失败及警告问题
原代码
import matplotlib.pyplot as plt import pandas as pd #750k_mesh df1=pd.read_excel("Filelocation/tcdata_750K_mesh.xlsx", "tcdata_750K_mesh", usecols='B:E',skiprows=5 ) df1_x1 = pd.DataFrame(df1, columns= ['Unnamed: 1']) df1_y1 = pd.DataFrame(df1, columns= ['Unnamed: 2']) df1_y2 = pd.DataFrame(df1, columns= ['Unnamed: 3']) df1_y3 = pd.DataFrame(df1, columns= ['Unnamed: 4']) #1.5M_mesh df2=pd.read_excel("Filelocation//tcdata_1.5M_mesh.xlsx", "tcdata_1.5M_mesh", usecols='B:E',skiprows=5 ) df2_x1 = pd.DataFrame(df2, columns= ['Unnamed: 1']) df2_y1 = pd.DataFrame(df2, columns= ['Unnamed: 2']) df2_y2 = pd.DataFrame(df2, columns= ['Unnamed: 3']) df2_y3 = pd.DataFrame(df2, columns= ['Unnamed: 4']) #3M_mesh df3=pd.read_excel("Filelocation//tcdata_3M_mesh.xlsx", "tcdata_3M_mesh", usecols='B:E',skiprows=5 ) df3_x1 = pd.DataFrame(df3, columns= ['Unnamed: 1']) df3_y1 = pd.DataFrame(df3, columns= ['Unnamed: 2']) df3_y2 = pd.DataFrame(df3, columns= ['Unnamed: 3']) df3_y3 = pd.DataFrame(df3, columns= ['Unnamed: 4']) #9M_mesh df4=pd.read_excel("Filelocation//tcdata_9M_mesh.xlsx", "tcdata_9M_mesh", usecols='B:E',skiprows=5 ) df4_x1 = pd.DataFrame(df4, columns= ['Unnamed: 1']) df4_y1 = pd.DataFrame(df4, columns= ['Unnamed: 2']) df4_y2 = pd.DataFrame(df4, columns= ['Unnamed: 3']) df4_y3 = pd.DataFrame(df4, columns= ['Unnamed: 4']) linewidth=1 markersize=0.25 markernumber=10 ax1 = plt.plot(df1_x1,df1_y1,'b-', linewidth=linewidth,markevery=markernumber,label='750K'), ax1 = plt.plot(df2_x1,df2_y1,'g-', linewidth=linewidth,markevery=markernumber,label='1.5M'), ax1 = plt.plot(df3_x1,df3_y1,'r-',linewidth=linewidth,markevery=markernumber,label='3M'), ax1 = plt.plot(df4_x1,df4_y1,'c-', linewidth=linewidth,markevery=markernumber,label='9M'), ax1 = plt.ylabel('Temperature (''$^\circ$''C)'), ax1 = plt.xlabel('Time (s)'), ax1 = plt.axis([-1,17, 1200,1550]) ax1 = plt.xticks(fontsize=10) ax1 = plt.yticks(fontsize=10) ax1 = leg = plt.legend(loc=1,fontsize=10) ax1 = leg.get_frame().set_edgecolor('k') ax1 = leg.get_frame().set_facecolor('w') # this is an inset axes over the main axes ax2 = plt.axes([.22, .22, .28, .28], facecolor='w') #x1,y1, x2, y2 location of the subplot in the current figure ax2 = plt.plot(df1_x1,df1_y1,'b-', linewidth=linewidth,markevery=markernumber,label='750K'), ax2 = plt.plot(df2_x1,df2_y1,'g-', linewidth=linewidth,markevery=markernumber,label='1.5M'), ax2 = plt.plot(df3_x1,df3_y1,'r-',linewidth=linewidth,markevery=markernumber,label='3M'), ax2 = plt.plot(df4_x1,df4_y1,'c-', linewidth=linewidth,markevery=markernumber,label='9M'), ax2 = ax3=plt.axis([12,14, 1280,1320]) ax2 = plt.xticks(fontsize=7) ax2 = plt.yticks(fontsize=7) fig_1 = plt.figure(1) fig_2 = fig_1.add_subplot(111) fig_2.grid(color='#929591', linestyle='--', linewidth=0.5) plt.show() plt.draw() fig_1.savefig('grid_independency_test.png', dpi=1000)
问题现象
- 可正常绘制主图+内嵌子图,但无法保存图像到指定目录
- 收到Matplotlib弃用警告:
MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.
- 控制台输出:
fig_2 = fig_1.add_subplot(111)
return (<Figure size 432x288 with 0 Axes> )
问题原因及解决方案
1. 图像保存失败的原因
代码中先调用plt.show(),这个函数会弹出图形窗口并清空当前Figure对象的内容,后续调用fig_1.savefig()时,fig_1已经是空白状态,因此无法保存正确图像。
解决办法:调整保存和显示的顺序,把savefig移到show之前:
fig_1.savefig('grid_independency_test.png', dpi=1000) plt.show() plt.draw()
2. 弃用警告的原因
代码混用了Matplotlib的面向对象API和pyplot状态机API:
- 前面用
plt.plot()等函数时,Matplotlib会自动创建默认的Figure和Axes实例 - 后续又执行
fig_1 = plt.figure(1)和fig_2 = fig_1.add_subplot(111),试图给已存在的Figure(1)重复添加子图,触发了Axes实例复用的警告。
解决办法:统一使用面向对象API,重构后的完整代码:
import matplotlib.pyplot as plt import pandas as pd # 读取数据 df1=pd.read_excel("Filelocation/tcdata_750K_mesh.xlsx", "tcdata_750K_mesh", usecols='B:E',skiprows=5 ) df1_x1 = df1['Unnamed: 1'] df1_y1 = df1['Unnamed: 2'] df2=pd.read_excel("Filelocation//tcdata_1.5M_mesh.xlsx", "tcdata_1.5M_mesh", usecols='B:E',skiprows=5 ) df2_x1 = df2['Unnamed: 1'] df2_y1 = df2['Unnamed: 2'] df3=pd.read_excel("Filelocation//tcdata_3M_mesh.xlsx", "tcdata_3M_mesh", usecols='B:E',skiprows=5 ) df3_x1 = df3['Unnamed: 1'] df3_y1 = df3['Unnamed: 2'] df4=pd.read_excel("Filelocation//tcdata_9M_mesh.xlsx", "tcdata_9M_mesh", usecols='B:E',skiprows=5 ) df4_x1 = df4['Unnamed: 1'] df4_y1 = df4['Unnamed: 2'] linewidth=1 markersize=0.25 markernumber=10 # 创建主图的Figure和Axes fig_1, ax1 = plt.subplots(figsize=(6,4)) # 主图绘图 ax1.plot(df1_x1,df1_y1,'b-', linewidth=linewidth,markevery=markernumber,label='750K') ax1.plot(df2_x1,df2_y1,'g-', linewidth=linewidth,markevery=markernumber,label='1.5M') ax1.plot(df3_x1,df3_y1,'r-',linewidth=linewidth,markevery=markernumber,label='3M') ax1.plot(df4_x1,df4_y1,'c-', linewidth=linewidth,markevery=markernumber,label='9M') # 设置主图属性 ax1.set_ylabel('Temperature ($^\circ$C)') ax1.set_xlabel('Time (s)') ax1.set_xlim(-1,17) ax1.set_ylim(1200,1550) ax1.tick_params(axis='both', labelsize=10) # 配置图例 leg = ax1.legend(loc=1,fontsize=10) leg.get_frame().set_edgecolor('k') leg.get_frame().set_facecolor('w') # 添加网格 ax1.grid(color='#929591', linestyle='--', linewidth=0.5) # 创建内嵌子图,添加唯一label消除警告 ax2 = fig_1.add_axes([.22, .22, .28, .28], facecolor='w', label='inset_axes') ax2.plot(df1_x1,df1_y1,'b-', linewidth=linewidth,markevery=markernumber) ax2.plot(df2_x1,df2_y1,'g-', linewidth=linewidth,markevery=markernumber) ax2.plot(df3_x1,df3_y1,'r-',linewidth=linewidth,markevery=markernumber) ax2.plot(df4_x1,df4_y1,'c-', linewidth=linewidth,markevery=markernumber) # 设置子图属性 ax2.set_xlim(12,14) ax2.set_ylim(1280,1320) ax2.tick_params(axis='both', labelsize=7) # 先保存再显示 fig_1.savefig('grid_independency_test.png', dpi=1000) plt.show()
额外优化点
- 无需将单列DataFrame重复转换,直接用
df['列名']获取Series即可,代码更简洁 - 用
set_xlim()/set_ylim()替代plt.axis(),更符合面向对象编程风格 - 给内嵌子图添加
label='inset_axes'参数,彻底消除弃用警告
内容的提问来源于stack exchange,提问作者User646972
相关产品推荐
相关产品推荐

