Python seaborn按分组绘制1行3列回归子图并导出PDF
数据集与需求说明
- 数据集包含3组调研数据(exp1、exp2、exp3)
- 每组调研包含2个试次(trial1、trial2)
- 每个试次采集3项特征(feature1、feature2、feature3)及对应目标变量值
- 需求为按[调研,试次]分组,每组生成1行3列的子图画布放置3个特征的回归拟合图,所有分组结果统一保存到单个PDF文件。
原代码问题点
- 未提前创建子图网格,每次绘制特征图都生成独立画布,无法实现同组图排布在同一页
- 存在变量拼写错误:
trialtrial为笔误,取目标变量列时data[target]未加引号,会触发运行报错 - PDF保存、画布关闭逻辑放在特征循环内部,导致单张特征图单独占PDF页面
修改后完整代码
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from matplotlib.backends.backend_pdf import PdfPages from scipy import stats data = {'Trial': ['trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial1', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2', 'trial2'], 'Survey': ['exp1', 'exp1', 'exp1', 'exp1', 'exp1', 'exp1', 'exp1', 'exp1', 'exp1', 'exp1', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp1', 'exp1', 'exp1', 'exp1', 'exp1', 'exp1', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp2', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3', 'exp3'], 'feature1': [0.76, 0.72, 0.76, 0.73, 0.69, 0.76, 0.74, 0.71, 0.67, 0.74, 0.74, 0.68, 0.73, 0.67, 0.63, 0.73, 0.72, 0.7, 0.59, 0.7, 0.63, 0.52, 0.57, 0.49, 0.46, 0.59, 0.59, 0.55, 0.42, 0.55, 0.69, 0.75, 0.72, 0.8, 0.79, 0.69, 0.65, 0.73, 0.68, 0.8, 0.79, 0.79, 0.76, 0.52, 0.6, 0.53, 0.71, 0.71, 0.71, 0.64, 0.53], 'feature2': [0.59, 0.55, 0.6, 0.56, 0.51, 0.6, 0.54, 0.51, 0.48, 0.57, 0.65, 0.57, 0.63, 0.56, 0.51, 0.64, 0.6, 0.56, 0.46, 0.6, 0.48, 0.36, 0.4, 0.32, 0.3, 0.43, 0.41, 0.36, 0.26, 0.38, 0.49, 0.57, 0.53, 0.65, 0.64, 0.5, 0.52, 0.61, 0.55, 0.75, 0.73, 0.73, 0.65, 0.34, 0.43, 0.35, 0.58, 0.58, 0.57, 0.48, 0.34], 'feature3': [0.32, 0.28, 0.29, 0.28, 0.25, 0.3, 0.29, 0.28, 0.24, 0.28, 0.28, 0.23, 0.24, 0.22, 0.2, 0.25, 0.25, 0.24, 0.19, 0.23, 0.22, 0.17, 0.18, 0.16, 0.16, 0.19, 0.2, 0.19, 0.15, 0.18, 0.27, 0.31, 0.27, 0.35, 0.35, 0.25, 0.23, 0.26, 0.23, 0.32, 0.3, 0.31, 0.28, 0.2, 0.21, 0.19, 0.25, 0.24, 0.24, 0.21, 0.2], 'target': [91, 88, 87, 87, 86, 89, 85, 86, 85, 87, 91, 88, 87, 87, 86, 89, 85, 86, 85, 87, 91, 88, 87, 87, 86, 89, 85, 86, 85, 87, 85, 88, 87, 93, 94, 86, 85, 88, 87, 93, 94, 91, 90, 85, 88, 87, 93, 94, 91, 90, 83]} df = pd.DataFrame(data) feature_list = ['feature1', 'feature2', 'feature3'] with PdfPages('regplot_example.pdf') as pdf: for (survey, trial), group_data in df.groupby(['Survey','Trial']): regResult_perSurvey = dict() print(f'processing: {survey} {trial}') # 提前创建1行3列的子图画布,设置合适尺寸 fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15, 4.5)) for idx, feature in enumerate(feature_list): ax = axes[idx] # 拟合回归模型,修正原代码target未加引号的问题 slope, intercept, r_value, p_value, std_err = stats.linregress(group_data[feature], group_data['target']) # 修正原代码trialtrial笔误 regResult_perSurvey[f'{survey}:{trial}:{feature}'] = [ survey, trial, feature, f'{r_value:.2f}', f'{p_value:.2e}', f'{std_err:.2f}' ] # 在指定子图上绘制回归图 sns.regplot( x=feature, y='target', data=group_data, ax=ax, scatter_kws={'color':'black', 'alpha':0.7}, line_kws={ 'color':'red', 'label':f"y={slope:.1f}x+{intercept:.1f}\n$R^2: {r_value**2:.2f}$" } ) ax.set_title(f'{survey} {trial} {feature}') ax.legend() # 同组3张图全部绘制完成后统一调整布局、保存 plt.tight_layout() # 如需保存单组整图可放开下一行注释 # plt.savefig(f'regplot_{survey}_{trial}.png', dpi=300, bbox_inches='tight') pdf.savefig(fig, bbox_inches='tight') plt.close(fig) # 如需导出回归统计结果可放开下部分注释 # res_df = pd.DataFrame(regResult_perSurvey, index=['Survey','Trial','Feature','r','p','std_err']).T # res_df.to_csv('regression_results.csv', index=False)
代码说明
- 每个[调研,试次]分组对应PDF内1页,页面横向排列3个特征的回归子图
- 保留原有黑色散点、红色拟合线、回归公式与拟合优度标注样式,散点增加透明度避免重叠遮挡
- 修复原代码所有语法笔误,回归统计结果的存储逻辑保留,可直接导出为CSV汇总
- 画布尺寸、样式参数可根据实际需求调整
figsize、scatter_kws、line_kws内的配置
内容的提问来源于stack exchange,提问作者Amilovsky
相关产品推荐
相关产品推荐

