📅 系列:一起学Python | 难度:⭐⭐⭐
🔗 上期回顾:第112天:饼图
柱状图对比的是不同类别的高低,而直方图(Histogram)看的是同一组数据的分布。
它能回答三个关键问题:
📍 中心在哪? 数据集中在哪个区间?
📐 偏不偏? 是左偏(长尾在左)还是右偏(长尾在右)?
👀 有没有异常值? 有没有远离主体的"孤胆英雄"?
一句话:直方图是探索性数据分析(EDA)的必备武器。
hist() 参数全解析matplotlib.pyplot.hist(x, bins=None, range=None, density=False,cumulative=False, histtype='bar',align='mid', orientation='vertical',rwidth=None, color=None, alpha=None,stacked=False, label=None)
x | np.random.randn(1000) | |
bins | 1030、50 | |
range | (0, 100) | |
density | FalseTrue(密度) | |
cumulative | FalseTrue | |
histtype | 'bar''step'、'stepfilled' | |
align | 'left''mid'(默认)、'right' | |
orientation | 'vertical''horizontal' | |
rwidth | 0.81.0(无缝) | |
color | 'skyblue''#2E86AB' | |
alpha | 0.5 | |
stacked | FalseTrue | |
edgecolor | 'white''black' |
import numpy as npimport matplotlib.pyplot as pltimport matplotlib.font_manager as fmimport os# ================= 1. 字体加载(解决报错的核心) =================font_path = "simhei.ttf" # 确保你已经在当前目录上传了 simhei.ttfif not os.path.exists(font_path):font_path = "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc" # 备用系统字体prop = fm.FontProperties(fname=font_path)plt.rcParams['axes.unicode_minus'] = False# 生成1000个标准正态分布随机数data = np.random.randn(1000)plt.figure(figsize=(10, 6))plt.hist(data, bins=30, color='skyblue', edgecolor='white', alpha=0.8)plt.title('标准正态分布直方图', fontproperties=prop, fontsize=16)plt.xlabel('数值', fontproperties=prop)plt.ylabel('频数', fontproperties=prop)plt.grid(True, alpha=0.3, linestyle='--')plt.show()

效果:经典的"钟形曲线"轮廓,中间高、两边低。
💡 bins 调参技巧:bins 太少会丢失细节(变成几座大山),太多会过于稀疏(变成刺猬)。数据量1000时,bins=20~40 最合适。
# 三组不同分布的数据data1 = np.random.normal(0, 1, 1000) # 均值0,标准差1data2 = np.random.normal(2, 1, 1000) # 均值2,标准差1data3 = np.random.normal(-2, 1, 1000) # 均值-2,标准差1plt.figure(figsize=(10, 6))plt.hist(data1, bins=30, alpha=0.5, label='A组(均值0)', color='#2E86AB')plt.hist(data2, bins=30, alpha=0.5, label='B组(均值2)', color='#E74C3C')plt.hist(data3, bins=30, alpha=0.5, label='C组(均值-2)', color='#27AE60')plt.title('三组数据分布对比', fontproperties=prop, fontsize=16)plt.xlabel('数值', fontproperties=prop)plt.ylabel('频数', fontproperties=prop)plt.legend(prop=prop)plt.grid(True, alpha=0.3)plt.show()

alpha=0.5 是关键:多组直方图叠加时,透明度必须调低,否则颜色会糊成一团。data = np.random.normal(170, 10, 1000) # 身高数据:均值170,标准差10plt.figure(figsize=(10, 6))# density=True:y轴变为概率密度,所有柱子面积之和 = 1plt.hist(data, bins=30, density=True,color='#9B59B6', edgecolor='white', alpha=0.7)# 叠加理论正态分布曲线from scipy import statsxmin, xmax = plt.xlim()x = np.linspace(xmin, xmax, 100)plt.plot(x, stats.norm.pdf(x, 170, 10), 'r--', linewidth=2, label='理论曲线')plt.title('身高分布概率密度', fontproperties=prop, fontsize=16)plt.xlabel('身高(cm)', fontproperties=prop)plt.ylabel('概率密度', fontproperties=prop)plt.legend(prop=prop)plt.grid(True, alpha=0.3)plt.show()

data = np.random.randn(1000)plt.figure(figsize=(10, 6))# cumulative=True:累积频数/概率plt.hist(data, bins=30, cumulative=True, density=True,color='#F39C12', edgecolor='white', alpha=0.8)plt.title('累积分布函数(CDF)', fontproperties=prop, fontsize=16)plt.xlabel('数值', fontproperties=prop)plt.ylabel('累积概率', fontproperties=prop)plt.grid(True, alpha=0.3)plt.show()

data = np.random.randn(1000)fig, axes = plt.subplots(1, 3, figsize=(15, 5))# bar(默认)axes[0].hist(data, bins=20, histtype='bar', color='#3498DB', edgecolor='white')axes[0].set_title('bar(默认)', fontproperties=prop)# step(无填充阶梯)axes[1].hist(data, bins=20, histtype='step', color='#E74C3C', linewidth=2)axes[1].set_title('step(线条)', fontproperties=prop)# stepfilled(填充阶梯)axes[2].hist(data, bins=20, histtype='stepfilled', color='#2ECC71', alpha=0.7)axes[2].set_title('stepfilled(填充阶梯)', fontproperties=prop)plt.suptitle('直方图样式对比', fontproperties=prop, fontsize=14)plt.tight_layout()plt.show()

import pandas as pd# 生成数据data = pd.Series(np.random.normal(170, 10, 250))plt.figure(figsize=(10, 6))# 直接用 plt.hist() 传入 Pandas Seriesplt.hist(data, bins=15, color='#1ABC9C', edgecolor='white', alpha=0.8)# 添加统计信息mean = data.mean()std = data.std()plt.axvline(mean, color='red', linestyle='--', linewidth=2, label=f'均值: {mean:.1f}')plt.axvline(mean + std, color='orange', linestyle=':', linewidth=2, label=f'±1σ')plt.axvline(mean - std, color='orange', linestyle=':', linewidth=2)plt.title('Pandas 数据直方图 + 统计标注', fontproperties=prop, fontsize=16)plt.xlabel('数值', fontproperties=prop)plt.ylabel('频数', fontproperties=prop)plt.legend(prop=prop)plt.grid(True, alpha=0.3)plt.show()



# 基础直方图plt.hist(data, bins=30)# 美化版plt.hist(data, bins=30, color='skyblue', edgecolor='white', alpha=0.8)# 概率密度plt.hist(data, bins=30, density=True)# 累积分布plt.hist(data, bins=30, cumulative=True, density=True)# 多组对比plt.hist(data1, bins=30, alpha=0.5, label='A组')plt.hist(data2, bins=30, alpha=0.5, label='B组')plt.legend()# 阶梯样式plt.hist(data, bins=30, histtype='step', linewidth=2)
基础题:生成500个均值为50、标准差为15的随机数,绘制直方图,bins=25
进阶题:绘制两组学生成绩的直方图(A班均值75,B班均值82),用透明度叠加对比
挑战题:绘制概率密度直方图,并叠加正态分布理论曲线,标注均值和标准差线
今天我们掌握了 Matplotlib 直方图的核心技能:
✅ plt.hist() —— 基础直方图,探索数据分布
✅ bins —— 控制粒度,太少丢细节,太多变稀疏
✅ density=True —— 概率密度,面积=概率
✅ cumulative=True —— 累积分布,看"从小到大"的累加
✅ histtype —— bar/step/stepfilled,风格切换
✅ 多组叠加 —— alpha 透明度是关键
✅ 与 Pandas 结合 —— 数据分析流程无缝衔接
关键记忆:直方图看分布,柱状图看对比;bins 是分辨率,density 是概率尺。
