如何在FacetGrid中绘制多直方图?子图列映射错误修复方案
解决DataFrame多列直方图布局映射错误问题
问题背景
现有一个包含95列的DataFrame,列名格式为{指标}_phase{时段}_{统计类型},统计类型包括Max、Min、Avg。需要绘制3列32行的子图布局:
- 第1列(索引0):展示所有Max值的直方图
- 第2列(索引1):展示所有Avg值的直方图
- 第3列(索引2):展示所有Min值的直方图
- 每行对应一个指标+时段组合(如
Var1_phase2对应一行)
当前代码使用int(i/3)来确定行索引,但由于部分指标时段缺少Min列,导致列索引的分组逻辑混乱,出现直方图映射到错误行的问题。
原因分析
原代码依赖列的遍历索引i,通过int(i/3)计算行位置,但列列表并非严格按每3个(Avg/Max/Min)为一组排列(例如Var2的部分时段只有Avg和Max列),这种计算方式会将不同指标时段的列错误分配到同一行。
解决方案
通过提取列名的前缀({指标}_phase{时段})进行分组,每个唯一前缀对应一行子图,再分别匹配对应的Max、Avg、Min列绘制到对应列的子图中:
import matplotlib.pyplot as plt import seaborn as sns # 创建画布 fig, axes = plt.subplots(nrows=32, ncols=3, figsize=(20, 96)) columnas_numeric = df_agg_new.select_dtypes(include=['float64', 'int64']).columns columnas_numeric = columnas_numeric.drop('season') # 提取所有列的前缀(去掉末尾的_Avg/_Max/_Min) prefixes = [col.rsplit('_', 1)[0] for col in columnas_numeric] # 获取唯一前缀,每个前缀对应一行(保持原顺序) unique_prefixes = list(dict.fromkeys(prefixes)) # 遍历每个唯一前缀(对应每一行) for row_idx, prefix in enumerate(unique_prefixes): # 匹配对应统计类型的列 max_col = f"{prefix}_Max" avg_col = f"{prefix}_Avg" min_col = f"{prefix}_Min" # 绘制Max到第1列(索引0) if max_col in columnas_numeric: sns.histplot( data=df_agg_new, x=max_col, stat="count", kde=True, line_kws={'linewidth': 2}, alpha=0.3, ax=axes[row_idx][0] ) axes[row_idx][0].set_title(max_col, fontsize=7, fontweight="bold") axes[row_idx][0].tick_params(labelsize=6) axes[row_idx][0].set_xlabel("") # 绘制Avg到第2列(索引1) if avg_col in columnas_numeric: sns.histplot( data=df_agg_new, x=avg_col, stat="count", kde=True, line_kws={'linewidth': 2}, alpha=0.3, ax=axes[row_idx][1] ) axes[row_idx][1].set_title(avg_col, fontsize=7, fontweight="bold") axes[row_idx][1].tick_params(labelsize=6) axes[row_idx][1].set_xlabel("") # 绘制Min到第3列(索引2) if min_col in columnas_numeric: sns.histplot( data=df_agg_new, x=min_col, stat="count", kde=True, line_kws={'linewidth': 2}, alpha=0.3, ax=axes[row_idx][2] ) axes[row_idx][2].set_title(min_col, fontsize=7, fontweight="bold") axes[row_idx][2].tick_params(labelsize=6) axes[row_idx][2].set_xlabel("") # 调整布局 fig.tight_layout() plt.subplots_adjust(top=0.97) fig.suptitle('Distribution plots', fontsize=10, fontweight="bold");
说明
- 前缀分组:通过
rsplit('_', 1)[0]提取列名的指标+时段前缀,确保每个唯一前缀对应一行子图,不受列数多少影响 - 存在性检查:通过
if col in columnas_numeric判断列是否存在,避免因缺少Min列导致的报错 - 严格对应:每个前缀的Max/Avg/Min列会被精确绘制到对应行的指定列,完全匹配预期布局
内容的提问来源于stack exchange,提问作者Pablo Moreira Garcia
相关产品推荐
相关产品推荐

