使用for循环实现子图绘制:matplotlib与stats.probplot结合问题
解决方案:Matplotlib子图布局配合SciPy概率图
问题核心
你之前的代码错误在于没有正确给stats.probplot指定子图的坐标轴对象,plot=plt(axes[n])是无效写法,stats.probplot的plot参数需要直接传入matplotlib.axes.Axes实例。
完整可运行代码
import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy import stats # 1. 准备数据(修正原代码变量名错误) labels = ['hc','svppa','nfvppa','lvppa'] df = { "id": list(range(1,21,1)), "label": list(np.repeat(labels, 5)), "col1": list(np.random.normal(100,10,size=20)), "col2": list(np.random.normal(100,10,size=20)), "col3": list(np.random.normal(100,10,size=20)), "col4": list(np.random.normal(100,10,size=20)), "col5": list(np.random.normal(100,10,size=20)), "col6": list(np.random.normal(100,10,size=20)), "col7": list(np.random.normal(100,10,size=20)) } df = pd.DataFrame(df) # 2. 提取需要分析的特征列 columns = list(df.columns[2:]) num_cols = len(columns) num_labels = len(labels) # 3. 创建子图网格:每行对应一个特征列,每列对应一个分组label fig, axes = plt.subplots(nrows=num_cols, ncols=num_labels, figsize=(15, 3*num_cols), sharex=True, sharey=True) plt.subplots_adjust(hspace=0.4, wspace=0.3) # 4. 遍历绘制每个子图的概率图 for row_idx, col in enumerate(columns): for col_idx, label in enumerate(labels): # 获取当前子图的坐标轴对象 ax = axes[row_idx, col_idx] # 绘制概率图并指定到当前坐标轴 stats.probplot(df[df['label'] == label][col], dist='norm', plot=ax) # 设置子图标题 ax.set_title(f"Probability plot {col} - {label}", fontsize=10) # 隐藏重复的坐标轴标签,优化布局整洁度 if row_idx != num_cols - 1: ax.set_xlabel('') if col_idx != 0: ax.set_ylabel('') plt.show()
关键细节说明
- 子图索引对应:
axes[row_idx, col_idx]中,行索引对应特征列、列索引对应分组label,完美匹配“每行一个特征,每列一个分组”的展示布局。 stats.probplot参数正确用法:直接传入子图的ax对象,就能将概率图绘制在指定子图中,而非默认的全局画布。- 布局优化:通过
hspace和wspace调整子图间距,根据特征列数动态设置画布高度,隐藏重复坐标轴标签减少视觉冗余。
最终效果
运行代码后会生成网格状子图:
- 每行对应
col1-col7中的一个特征 - 每列对应
hc/svppa/nfvppa/lvppa中的一个分组 - 每个子图为对应分组下该特征的正态概率图,完全满足展示需求
内容的提问来源于stack exchange,提问作者EduardoRod
相关产品推荐
相关产品推荐

