如何对每个分布组分别归一化并绘制面积为1的直方图
实现每个类别独立归一化的直方图
假设你有如下DataFrame:
CATEGORY Value a v1 a v2 a v3 a v4 a v5 b v6 b v7 b v8
如果用seaborn.histplot按CATEGORY绘制分布,代码如下:
sns.histplot(data, "Value", hue="CATEGORY", stat="percent")
但这里存在问题:类别a占总样本的5/8,类别b占3/8,直方图会直接反映这个占比。而你需要让每个类别的直方图面积独立归一化为1,也就是每个类别内部的占比总和为100%,不受总样本占比影响。
方法一:利用seaborn内置参数直接实现
seaborn的histplot本身支持这个需求,不需要手动遍历类别。只需要将stat设为"density",同时设置common_norm=False,这样每个类别会独立计算密度,确保自身面积为1:
import seaborn as sns import matplotlib.pyplot as plt sns.histplot(data, "Value", hue="CATEGORY", stat="density", common_norm=False) plt.show()
common_norm=False的核心作用就是关闭全局归一化逻辑,改为每个类别单独做归一化处理,完美匹配你的需求。
方法二:手动遍历类别绘制(精细化控制)
如果需要对每个类别做更个性化的调整(比如自定义bins、颜色、透明度等),可以遍历每个类别单独绘制:
import seaborn as sns import matplotlib.pyplot as plt # 获取所有唯一类别 categories = data["CATEGORY"].unique() for cat in categories: # 提取当前类别的数据子集 subset = data[data["CATEGORY"] == cat] # 单独绘制该类别的归一化直方图 sns.histplot(subset["Value"], stat="density", label=cat) # 添加图例 plt.legend() plt.show()
这种方式自由度更高,适合需要针对不同类别做差异化设置的场景。
内容的提问来源于stack exchange,提问作者Martin Beraldo
相关产品推荐
相关产品推荐

