如何在Matplotlib中绘制含可控宽度水平直方图的分位数折线图?
Matplotlib实现分位数折线+固定宽度水平密度直方图
核心思路
- 先绘制主图的分位数折线
- 通过嵌入子轴(
inset_axes)在指定x位置添加水平直方图,通过坐标换算控制直方图的固定宽度 - 启用
density=True确保直方图为密度分布
完整代码示例
import matplotlib.pyplot as plt import numpy as np from scipy.stats.mstats import mquantiles # 1. 准备数据 x = np.arange(0, 11) # x取值0到10 # 模拟每个x对应的[0,60]数值组,每组1000个样本 data_groups = [np.random.normal(loc=i*5 + 20, scale=8, size=1000) for i in x] # 计算每个组的中位数(可替换为其他分位数,比如0.25/0.75) quantile_vals = [mquantiles(group, prob=0.5)[0] for group in data_groups] # 2. 创建主图并绘制分位数折线 fig, main_ax = plt.subplots(figsize=(10, 6)) main_ax.plot(x, quantile_vals, color='black', marker='s', linestyle='-', linewidth=2, label='中位数') main_ax.set_xlabel('x') main_ax.set_ylabel('数值') main_ax.set_xlim(-1, 11) # 给两侧留出空间 main_ax.set_ylim(0, 65) main_ax.legend() main_ax.grid(axis='y', alpha=0.3) # 3. 定义添加固定宽度水平直方图的函数 def add_fixed_width_hist(ax, x_pos, data, hist_width=0.8, bins=12): """ 在指定x位置添加固定宽度的水平密度直方图 :param ax: 主图轴对象 :param x_pos: 直方图对应的x坐标 :param data: 该x位置对应的数值组 :param hist_width: 直方图在x轴上的固定宽度 :param bins: 直方图的区间数量 """ # 获取主图的坐标范围,换算嵌入轴的位置比例 x_min, x_max = ax.get_xlim() y_min, y_max = ax.get_ylim() # 计算嵌入轴的位置参数:[left, bottom, width, height](基于主图轴的比例) left_ratio = (x_pos - hist_width/2 - x_min) / (x_max - x_min) width_ratio = hist_width / (x_max - x_min) bottom_ratio = (y_min - y_min) / (y_max - y_min) height_ratio = (y_max - y_min) / (y_max - y_min) # 创建嵌入轴 hist_ax = ax.inset_axes([left_ratio, bottom_ratio, width_ratio, height_ratio], transform=ax.transAxes) # 绘制水平密度直方图 hist_ax.hist(data, bins=bins, density=True, orientation='horizontal', alpha=0.6, color='#666666') # 隐藏直方图的刻度,避免干扰主图 hist_ax.set_xticks([]) hist_ax.set_yticks([]) # 强制直方图y轴范围和主图一致 hist_ax.set_ylim(y_min, y_max) # 4. 给选定的x位置添加直方图(比如x=2、x=5) add_fixed_width_hist(main_ax, x_pos=2, data=data_groups[2], hist_width=0.8) add_fixed_width_hist(main_ax, x_pos=5, data=data_groups[5], hist_width=0.8) plt.tight_layout() plt.show()
关键细节说明
- 固定宽度控制:通过
hist_width参数直接设置直方图在x轴上的宽度(比如0.8代表占x轴0.8个单位长度),再通过坐标比例换算确保在主图中位置准确 - 密度直方图:
hist()函数中设置density=True,直方图的面积总和为1,反映数值分布的密度 - 嵌入轴处理:用
inset_axes创建的子轴完全贴合主图的y轴范围,隐藏自身刻度保证整体视觉整洁
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

