使用for循环将Seaborn图表保存至单个PDF时的异常问题求助
问题排查与解决方案
问题根源
你的代码中使用的sns.displot是Figure级绘图函数,它会自动创建全新的Figure对象,而你手动声明的fig = plt.figure(i,figsize=(8,4))并没有和这个绘图函数关联,因此这个fig始终是空的——这就是PDF中第一页空白的原因。
后续循环中,displot生成的新Figure会成为Matplotlib的当前活跃Figure,plt.savefig默认保存当前活跃Figure,所以PNG文件能正常生成;但pdf.savefig(fig)仍在保存你手动创建的空Figure,只是因为Matplotlib的状态管理机制,导致后续PDF页面看似正常,实际上逻辑是错误的。
修复方案
方案1:改用Axes级绘图函数(推荐)
使用sns.histplot(Axes级函数),可以在你手动创建的Figure/Axes上直接绘图,确保绘图内容与要保存的fig完全关联:
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from matplotlib.backends.backend_pdf import PdfPages pdf = PdfPages('Histogram.pdf') file='LD25_Percent_Error.txt' df_main=pd.read_csv(file, delimiter='\t') df_clean=df_main.loc[abs(df_main['obs_vel']) >=0.5] for sim in df_clean.sim.unique(): # 创建指定尺寸的Figure和Axes fig, ax = plt.subplots(figsize=(8,4)) df1=df_clean.loc[df_clean['sim'] == sim] # 在指定Axes上绘制直方图 sns.histplot(df1, x='% error', kde=True, ax=ax) ax.set_xlabel("% Error") ax.set_ylabel("Count") ax.set_title(f'Simulation: {sim}') plt.tight_layout() plt.savefig(f"sim_{sim}.png", bbox_inches='tight', dpi=150) pdf.savefig(fig) # 关闭当前Figure,避免内存占用和状态混乱 plt.close(fig) pdf.close()
方案2:使用displot返回的FacetGrid对象
如果你仍想使用sns.displot,可以直接获取它返回的FacetGrid对象的Figure,再保存到PDF:
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from matplotlib.backends.backend_pdf import PdfPages pdf = PdfPages('Histogram.pdf') file='LD25_Percent_Error.txt' df_main=pd.read_csv(file, delimiter='\t') df_clean=df_main.loc[abs(df_main['obs_vel']) >=0.5] for sim in df_clean.sim.unique(): df1=df_clean.loc[df_clean['sim'] == sim] # 使用displot并获取返回的FacetGrid对象,通过height和aspect控制尺寸 g = sns.displot(df1, x='% error', kde=True, height=4, aspect=2) g.set_xlabels("% Error") g.set_ylabels("Count") # 调整标题位置避免被遮挡 g.fig.suptitle(f'Simulation: {sim}', y=1.02) g.tight_layout() plt.savefig(f"sim_{sim}.png", bbox_inches='tight', dpi=150) # 保存FacetGrid对应的Figure到PDF pdf.savefig(g.fig) # 关闭Figure清理状态 plt.close(g.fig) pdf.close()
内容的提问来源于stack exchange,提问作者ZVY545
相关产品推荐
相关产品推荐

