Seaborn重叠直方图未按预期显示问题求助
解决Seaborn histplot双直方图无法正常重叠的问题
问题说明
使用Seaborn的histplot绘制两个直方图:
- 蓝色直方图对应完整数据集
total_means - 红色直方图对应
total_means中处于68%置信区间内的子集
但最终两个直方图未按预期重叠,呈现错位状态。
原代码如下:
import numpy as np from scipy.stats import norm import seaborn as sns import matplotlib.pyplot as plt data = np.sin(np.arange(0, 6*np.pi, 0.1)) * 100 sns.scatterplot(x=[np.mean(data)], y=[0]) sns.lineplot(data) population_size = 10000 sample_size = 100 total_means = [] for x in range(population_size): total_means.append(np.mean(np.random.choice(data, 100))) total_means = np.array(total_means) sns.histplot(total_means, kde=True) # 计算68%置信区间 from scipy.stats import norm z1 = norm.ppf(.50 - .68/2) se = np.array(data).std() / sample_size ** .5 x1 = z1 * se + np.array(data).mean() z2 = norm.ppf(.50 + .68/2) x2 = z2 * se + np.array(data).mean() print(x1, x2) plt.xticks(np.arange(total_means.min(), total_means.max(), 10)) plt.xticks(np.arange(0, 500, 100)) sns.histplot(total_means, kde=True) sns.histplot(total_means[(total_means >= x1) & (total_means <= x2)], kde=True, color='r')
原结果特征:蓝色与红色直方图错位,红色直方图未覆盖蓝色直方图的中间区域,坐标轴刻度显示异常。
问题根源
- 重复绘制完整数据集直方图:代码中先后两次调用
sns.histplot(total_means, kde=True),导致图层混乱 - 坐标轴刻度被强制覆盖:
plt.xticks(np.arange(0, 500, 100))将刻度强制设为0-500,但total_means均值接近0,导致直方图显示错位 - 子集直方图未对齐分箱:未指定
bins参数时,Seaborn会自动计算不同分箱,导致两个直方图无法重叠
修复方案
- 删除重复的完整数据集直方图绘制代码
- 基于
total_means实际范围设置坐标轴刻度 - 手动指定
bins参数,确保两个直方图分箱一致 - 添加
alpha参数设置透明度,便于观察重叠效果
修正后完整代码
import numpy as np from scipy.stats import norm import seaborn as sns import matplotlib.pyplot as plt # 生成原始数据 data = np.sin(np.arange(0, 6*np.pi, 0.1)) * 100 # 单独展示原始数据图,避免与直方图混叠 sns.scatterplot(x=[np.mean(data)], y=[0]) sns.lineplot(data) plt.show() # 生成样本均值数据集 population_size = 10000 sample_size = 100 total_means = [] for _ in range(population_size): total_means.append(np.mean(np.random.choice(data, sample_size))) total_means = np.array(total_means) # 计算68%置信区间 z1 = norm.ppf(.50 - .68/2) z2 = norm.ppf(.50 + .68/2) se = data.std() / np.sqrt(sample_size) x1 = z1 * se + data.mean() x2 = z2 * se + data.mean() print(f"68%置信区间:[{x1:.2f}, {x2:.2f}]") # 绘制对齐的直方图 bins = np.arange(total_means.min(), total_means.max(), 2) plt.figure(figsize=(10,6)) sns.histplot(total_means, kde=True, bins=bins, label='全部样本均值') sns.histplot(total_means[(total_means >= x1) & (total_means <= x2)], kde=True, bins=bins, color='r', alpha=0.5, label='68%置信区间内样本均值') # 设置可视化细节 plt.xticks(np.arange(total_means.min(), total_means.max(), 5)) plt.legend() plt.xlabel('样本均值') plt.ylabel('频数') plt.title('样本均值分布与68%置信区间子集') plt.show()
效果说明
修正后,红色直方图会准确覆盖在蓝色直方图的中间68%区域,透明度设置可清晰展示重叠部分,坐标轴刻度也匹配数据实际范围。
内容的提问来源于stack exchange,提问作者user8234870
相关产品推荐
相关产品推荐

