You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Plotly Express多分组直方图的概率密度总和为1?

Plotly Express多分组直方图概率密度总面积归一为1的实现方案

问题场景

给定示例数据集:

import pandas as pd
toy_df = pd.DataFrame({"value": [1, 12, 16, 4, 27, 38, 19], "group": [1, 1, 2, 1, 2, 2, 2]})

单分组时,使用px.histogram的histnorm='probability density'参数可生成总面积为1的直方图:

import plotly.express as px
px.histogram(toy_df, x="value", histnorm='probability density')

但添加color="group"分组后,Plotly会对每个分组单独归一概率密度,导致所有分组的总面积之和大于1。以下是两种在Plotly生态内的实现方案:


方案一:手动计算概率密度并使用Graph Objects构建

先获取全局分箱信息,再按分组计算基于全局总样本的概率密度,最后用plotly.graph_objects绘制:

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import numpy as np

toy_df = pd.DataFrame({"value": [1, 12, 16, 4, 27, 38, 19], "group": [1, 1, 2, 1, 2, 2, 2]})

# 获取全局分箱边界与宽度
fig_single = px.histogram(toy_df, x="value", histnorm='probability density')
bin_edges = fig_single.data[0].x
bin_width = bin_edges[1] - bin_edges[0]
total_samples = len(toy_df)

# 按分组统计各分箱样本数
grouped_counts = toy_df.groupby('group')['value'].apply(
    lambda x: np.histogram(x, bins=bin_edges)[0]
).unstack()

# 计算基于全局总样本的概率密度
prob_density = grouped_counts / (total_samples * bin_width)

# 构建直方图
fig = go.Figure()
for group in prob_density.index:
    fig.add_trace(go.Histogram(
        x=toy_df[toy_df['group'] == group]['value'],
        name=f'Group {group}',
        autobinx=False,
        xbins=dict(start=bin_edges[0], end=bin_edges[-1], size=bin_width),
        y=prob_density.loc[group].values
    ))

fig.update_layout(title='多分组概率密度直方图(总面积为1)', xaxis_title='value', yaxis_title='Probability Density')
fig.show()

方案二:利用样本权重实现(更简洁)

给每个样本赋予分组占总样本的比例作为权重,结合histnorm='probability density'参数,自动实现总面积归一为1:

import pandas as pd
import plotly.express as px

toy_df = pd.DataFrame({"value": [1, 12, 16, 4, 27, 38, 19], "group": [1, 1, 2, 1, 2, 2, 2]})

# 计算每个分组的样本占比作为权重
group_ratios = toy_df['group'].value_counts(normalize=True)
toy_df['weight'] = toy_df['group'].map(group_ratios)

# 带权重绘制直方图
fig = px.histogram(toy_df, x="value", color="group", histnorm='probability density', weights='weight')
fig.update_layout(title='多分组概率密度直方图(总面积为1)', xaxis_title='value', yaxis_title='Probability Density')
fig.show()

原理说明

方案二的核心逻辑是:每个分组的概率密度原本基于自身样本数归一,乘以分组占总样本的比例后,所有分组的面积总和等价于基于全局样本数归一的结果,最终总面积为1。

内容的提问来源于stack exchange,提问作者Janek Ziobro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 10:11:35