如何在Seaborn jointplot中绘制分组相对频率直方图?
解决jointplot小样本组边缘图无法显示的问题
因为jointplot的hue参数默认会对所有组使用全局归一化尺度,样本量小的组边缘分布会被大样本组压制,且norm_hist参数仅作用于联合图,无法影响边缘子图。可以通过JointGrid手动拆分数据绘制,让每个组的分布按自身归一化:
具体实现代码
import seaborn as sns import matplotlib.pyplot as plt # 初始化JointGrid,指定变量和数据集 g = sns.JointGrid(x=var_x, y=var_y, data=df) # 绘制每个条件的联合KDE(按自身归一化) for cond in df['condition'].unique(): subset = df[df['condition'] == cond] g.plot_joint( sns.kdeplot, data=subset, x=var_x, y=var_y, fill=True, alpha=0.7, label=cond, common_norm=False # 关键:每个组独立归一化,不共享全局尺度 ) # 处理X轴边缘图:绘制归一化的直方图+KDE ax_x = g.ax_marg_x for cond in df['condition'].unique(): subset = df[df['condition'] == cond] sns.histplot( data=subset, x=var_x, ax=ax_x, kde=True, stat='density', # stat='density'将直方图转为密度(归一化) alpha=0.5, label=cond ) ax_x.legend(title='Condition') # 处理Y轴边缘图:同理 ax_y = g.ax_marg_y for cond in df['condition'].unique(): subset = df[df['condition'] == cond] sns.histplot( data=subset, y=var_y, ax=ax_y, kde=True, stat='density', alpha=0.5, label=cond ) ax_y.legend(title='Condition') # 设置轴标签和标题 g.set_axis_labels(var_x, var_y) plt.suptitle('Normalized Joint Distribution by Condition', y=1.02) plt.show()
关键说明
- 用
JointGrid替代jointplot,获得对联合图、边缘子图的完全控制权 - 联合KDE的
common_norm=False:让每个组的密度分布按自身样本量计算,避免大样本组主导尺度 - 边缘图的
stat='density':将直方图转换为密度分布(总面积为1),确保小样本组的分布形状能正常显示,不会被大样本组的直方图覆盖
如果只想显示边缘KDE,把histplot替换为kdeplot即可:
sns.kdeplot(data=subset, x=var_x, ax=ax_x, fill=True, alpha=0.5, label=cond)
内容的提问来源于stack exchange,提问作者Alexis Cllmb
相关产品推荐
相关产品推荐

