Bokeh中创建双Y轴(计数/百分比)直方图的规范方法
双Y轴计数/百分比直方图的Bokeh规范实现
核心问题解决思路
- Y轴对齐:计数和百分比是线性转换关系(百分比 = 计数 / 样本总数 * 100),右侧Y轴范围必须基于左侧计数范围按同一比例换算,不能手动设置固定值。
- 右侧标签方向调整:通过
axis_label_orientation参数强制右侧Y轴标签和左侧保持垂直方向。 - 叠加PDF曲线:将PDF值转换为百分比刻度对应的高度(PDF值 * 区间宽度 * 100),确保和直方图刻度匹配。
完整代码示例
from bokeh.plotting import figure, show from bokeh.models import LinearAxis, Range1d import numpy as np from scipy.stats import norm # 生成模拟数据 np.random.seed(42) data = np.random.normal(loc=50, scale=10, size=1000) total = len(data) # 计算直方图参数 counts, edges = np.histogram(data, bins=15) bin_width = edges[1] - edges[0] percentages = counts / total * 100 # 转换为百分比 # 创建绘图对象,左侧Y轴为计数 p = figure( title="计数/百分比双Y轴直方图", x_axis_label="数值", y_axis_label="计数", tools="pan,box_zoom,reset,save", background_fill_color="#f5f5f5" ) # 绘制计数直方图 p.quad( top=counts, bottom=0, left=edges[:-1], right=edges[1:], fill_color="#3288bd", line_color="white", alpha=0.7 ) # 设置右侧Y轴范围:基于计数最大值换算出对应的百分比最大值 max_count = max(counts) max_percent = max_count / total * 100 p.extra_y_ranges["percent"] = Range1d(start=0, end=max_percent) # 添加右侧Y轴,调整标签方向与左侧一致 p.add_layout( LinearAxis( y_range_name="percent", axis_label="Percentage", axis_label_orientation=np.pi/2 # 垂直方向,和左侧Y轴标签一致 ), 'right' ) # 叠加正态分布PDF曲线(转换为百分比刻度) x = np.linspace(edges[0], edges[-1], 100) pdf = norm.pdf(x, loc=np.mean(data), scale=np.std(data)) # PDF转换为百分比高度:pdf值 * bin_width * 100(PDF积分是1,乘宽度得概率,再*100转百分比) pdf_percent = pdf * bin_width * 100 p.line( x=x, y=pdf_percent, line_color="#e34a33", line_width=2, legend_label="正态分布PDF", y_range_name="percent" ) p.legend.location = "top_right" show(p)
关键细节说明
- Y轴对齐保证:右侧Y轴范围
Range1d(start=0, end=max_percent)通过max_count / total *100计算得到,和左侧计数范围(0, max_count)严格成比例,刻度会完全对齐。 - 标签方向调整:
axis_label_orientation=np.pi/2强制右侧标签垂直显示,和左侧默认方向一致。 - PDF叠加逻辑:PDF原始值是概率密度,乘以区间宽度得到区间概率,再乘以100转换为百分比,确保曲线高度和直方图百分比柱对齐。
内容的提问来源于stack exchange,提问作者Lili
相关产品推荐
相关产品推荐

