news 2026/9/6 23:10:35

Data-Science-For-Beginners 第10课实战:用直方图与密度曲线可视化数据分布(Matplotlib + Seaborn 详解)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Data-Science-For-Beginners 第10课实战:用直方图与密度曲线可视化数据分布(Matplotlib + Seaborn 详解)

Data-Science-For-Beginners 第10课实战:用直方图与密度曲线可视化数据分布(Matplotlib + Seaborn 详解)

【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners

本文基于 Data-Science-For-Beginners 仓库 10-visualization-distributions 一课展开:以密歇根州鸟类数据集(birds.csv)为例,系统讲解如何用 Matplotlib 直方图刻画数值型分布、用分组叠加直方图刻画分类变量分布、再用 Seaborn 的 KDE 密度曲线做平滑可视化。读完本文,你将能独立完成从bins调参、数据过滤去偏到kdeplot分组密度绘图的完整分布分析流程,并理解每个关键参数的作用。

1. 课程背景:birds 数据集

本课承接第 9 课(用散点图发现 Minnesota 鸟类数据中的异常值、对比不同目鸟类的最大体长)。分布(distribution)回答的是"数据沿某个坐标轴如何组织"的问题,例如:400 多种鸟的最大翼展或最大体重的整体分布是什么样的?

课程使用仓库根目录下的 birds.csv,共 443 条鸟类记录、13 个字段:名称、学名、类别(Category)、目(Order)、科(Family)、属(Genus)、保护状态(ConservationStatus)以及体长/体重/翼展的上下限(MinLength、MaxLength、MinBodyMass、MaxBodyMass、MinWingspan、MaxWingspan)。在课程文件夹下的 notebook.ipynb 中导入 Pandas 与 Matplotlib 并加载数据(代码从课程文件夹运行,故数据路径为../../data/birds.csv):

import pandas as pd import matplotlib.pyplot as plt birds = pd.read_csv('../../data/birds.csv') birds.head()

前 5 行如下(与原课程文档一致):

NameScientificNameCategoryOrderFamilyGenusConservationStatusMinLengthMaxLengthMinBodyMassMaxBodyMassMinWingspanMaxWingspan
0Black-bellied whistling-duckDendrocygna autumnalisDucks/Geese/WaterfowlAnseriformesAnatidaeDendrocygnaLC475665210207694
1Fulvous whistling-duckDendrocygna bicolorDucks/Geese/WaterfowlAnseriformesAnatidaeDendrocygnaLC455371210508593
2Snow gooseAnser caerulescensDucks/Geese/WaterfowlAnseriformesAnatidaeAnserLC647920504050135165
3Ross's gooseAnser rossiiDucks/Geese/WaterfowlAnseriformesAnatidaeAnserLC57.36410661567113116
4Greater white-fronted gooseAnser albifronsDucks/Geese/WaterfowlAnseriformesAnatidaeAnserLC648119303310130165

2. 快速窥探分布:散点图的局限

课程先给出一个快速概览手段——散点图:

birds.plot(kind='scatter', x='MaxLength', y='Order', figsize=(12,8)) plt.title('Max Length per Order') plt.ylabel('Order') plt.xlabel('Max Length') plt.show()

它能给出"各目鸟类最大体长的整体布局",但并不是展示真实分布的最优方式——点的密集程度依赖肉眼估算。展示真实分布的任务通常由直方图(Histogram)完成。

3. 直方图:bins 参数、过滤与 2D 直方图

直方图类似条形图,但通过柱子的起伏(rise and fall)呈现分布形态;它要求数值型数据。构建方式是把数据数组划分成若干更小的"箱"(bins),展示各区间内取值数量。

3.1 基础直方图与 bins 调参

展示整个数据集的MaxBodyMass分布:

birds['MaxBodyMass'].plot(kind='hist', bins=10, figsize=(12,12)) plt.show()

可以看到,数据集中 400 多种鸟的 MaxBodyMass 大多落在 2000 以下的区间(左侧偏态明显,由大型雁形目物种把整体范围拉高所致)。

bins提高到 30,可以获得更细粒度的分布:

birds['MaxBodyMass'].plot(kind='hist', bins=30, figsize=(12,12)) plt.show()

bins是直方图最核心的参数:过小会掩盖分布细节(如 10 箱时只能看到"大部分集中在低端"),过大会引入噪声。课程建议尝试其他过滤器与数据点;若要查看完整分布,可去掉['MaxBodyMass']的列过滤。

3.2 用过滤消除偏态

上面的图偏态(skewed)明显,是因为少数超重型物种撑大了横轴范围。只筛选体重在 1g 到 60g 之间的小鸟、并使用 40 个 bins,可以得到一个"不那么偏态"的图:

filteredBirds = birds[(birds['MaxBodyMass'] > 1) & (birds['MaxBodyMass'] < 60)] filteredBirds['MaxBodyMass'].plot(kind='hist', bins=40, figsize=(12,12)) plt.show()

这里filteredBirds是一个用布尔掩码过滤出的子 DataFrame,后续文本数据与 KDE 部分都复用它。

3.3 2D 直方图:观察两个分布的关系

Matplotlib 还提供内置的 2D 直方图来比较两个变量的联合分布,并用更亮的颜色标示"汇聚点"(convergence):

x = filteredBirds['MaxBodyMass'] y = filteredBirds['MaxLength'] fig, ax = plt.subplots(tight_layout=True) hist = ax.hist2d(x, y)

从图中可以看出:体重与体长之间存在沿预期方向的相关性,并且有一个特别强的汇聚点——这正是用颜色密度代替散点堆叠的价值所在。

4. 文本(分类)数据的分布:保护状态 × 最小翼展

直方图默认面向数值数据,那么"按文本维度看分布"怎么办?birds 数据集中每个物种带有 IUCN 红色名录(IUCN Red List Categories)风格的保护状态缩写:

缩写含义
CRCritically Endangered(极危)
ENEndangered(濒危)
EXExtinct(灭绝)
LCLeast Concern(无危)
NTNear Threatened(近危)
VUVulnerable(易危)

课程把过滤后的filteredBirds按 6 种保护状态分别取出MinWingspan,用 6 条不同颜色、半透明(alpha=0.5)、相同分箱(bins=20)的直方图叠加,形成带标签的分类分布对比:

x1 = filteredBirds.loc[filteredBirds.ConservationStatus=='EX', 'MinWingspan'] x2 = filteredBirds.loc[filteredBirds.ConservationStatus=='CR', 'MinWingspan'] x3 = filteredBirds.loc[filteredBirds.ConservationStatus=='EN', 'MinWingspan'] x4 = filteredBirds.loc[filteredBirds.ConservationStatus=='NT', 'MinWingspan'] x5 = filteredBirds.loc[filteredBirds.ConservationStatus=='VU', 'MinWingspan'] x6 = filteredBirds.loc[filteredBirds.ConservationStatus=='LC', 'MinWingspan'] kwargs = dict(alpha=0.5, bins=20) plt.hist(x1, **kwargs, color='red', label='Extinct') plt.hist(x2, **kwargs, color='orange', label='Critically Endangered') plt.hist(x3, **kwargs, color='yellow', label='Endangered') plt.hist(x4, **kwargs, color='green', label='Near Threatened') plt.hist(x5, **kwargs, color='blue', label='Vulnerable') plt.hist(x6, **kwargs, color='gray', label='Least Concern') plt.gca().set(title='Conservation Status', ylabel='Min Wingspan') plt.legend()

这里的技术要点:用.loc[条件, 列]对分类字段做子集提取;用kwargs字典统一传递alpha(透明度,使叠加时彼此可见)与bins;最后用plt.legend()显示标签。

课程结论:最小翼展与保护状态之间似乎没有明显的相关性,并鼓励读者用同样方法测试数据集的其他字段、尝试不同过滤器,看能否找到真正的相关性。

5. 密度图(KDE):用 Seaborn 画平滑分布

5.1 从直方图到密度曲线

前面看到的直方图都是"阶梯状"的,不会形成平滑弧线。要展示更平滑的密度图,可以引入 Seaborn:

import seaborn as sns sns.kdeplot(filteredBirds['MinWingspan']) plt.show()

曲线形态与前面最小翼展直方图对应,只是更平滑。课程引用了 Seaborn 官方文档对 KDE 的定位:相对于直方图,KDE 能产生更不杂乱、更易于解读的图(尤其是绘制多个分布时),但当底层分布有界或不平滑时,KDE 也可能引入失真——"与直方图一样,表现质量也依赖于好的平滑参数选择"。换句话说,离群值仍然会让你的图"表现糟糕"。

5.2 bw_adjust:控制平滑程度

把第 3 节那张"锯齿状"的MaxBodyMass直方图用 KDE 重画:

sns.kdeplot(filteredBirds['MaxBodyMass']) plt.show()

如果想要"平滑但不过度平滑"的曲线,调整bw_adjust参数(带宽调整因子,取值越小带宽越窄、曲线越贴近原始波动):

sns.kdeplot(filteredBirds['MaxBodyMass'], bw_adjust=0.2) plt.show()

课程要求读者阅读该类型图的全部可用参数并动手实验。

5.3 分组密度:按鸟类目展示体重密度

只需几行代码,就能展示按鸟类目(Order)分组的最大体重密度,填充色块 + 各自归一化,适合对比多个子群体的形状:

sns.kdeplot( data=filteredBirds, x="MaxBodyMass", hue="Order", fill=True, common_norm=False, palette="crest", alpha=.5, linewidth=0, )

关键参数含义:hue指定分组字段;fill=True填充曲线下区域;common_norm=False表示各组独立归一化(比较"形状"而非"总量");palette/alpha/linewidth分别控制配色板、透明度与轮廓线宽。

5.4 双变量多密度叠加

还可以在同一张图里映射多个变量的密度。例如把体长(MinLength × MaxLength)与保护状态叠加:

sns.kdeplot(data=filteredBirds, x="MinLength", y="MaxLength", hue="ConservationStatus")

课程由此引出进一步思考:按体长聚类的 "Vulnerable"(易危)鸟群聚集是否有生物学意义?这正是一个从图表走向研究问题的入口。

6. 仓库实现佐证:solution notebook 中的真实运行证据

以上全部代码在仓库内都有可直接运行的完整实现:solution/notebook.ipynb 依次保存了"基础直方图 → 调整 bins → 过滤后新直方图 → MaxBodyMass×MaxLength 的 2D 直方图 → 保护状态叠加直方图 → MinWingspan KDE → MaxBodyMass KDE → bw_adjust 实验 → MinLength×MaxLength 双变量 KDE(hue=ConservationStatus)"全部单元格的执行输出,可与本文各节逐一对应复现。

从该 notebook 的运行记录还能得到两条实操层面的事实(均来自其保存的 stderr/警告输出,可推断为当时的运行环境特性):

  1. 在较早的 Matplotlib/Seaborn 组合下执行kdeplot会触发FutureWarning: Support for multi-dimensional indexing (e.g. obj[:, None]) is deprecated...,属于版本过渡期告警,不影响出图;
  2. 双变量 KDE(MinLength×MaxLength)运行时会提示UserWarning: Dataset has 0 variance; skipping density estimate.——说明某个(小样本)分组在某个方向上方差为 0 而被跳过。可以推断:分组 KDE 对样本量极少的类别并不稳健,这也是课程建议"研究 VU 聚集是否有意义"背后的方法论提醒。

另请注意:课程 README 中 2D 直方图小节还演示了from matplotlib import colors/PercentFormatter的可选导入(见 solution notebook 对应单元格),用于自定义 2D 直方图的颜色标尺。

7. 关键参数速查

参数所属函数作用与取值说明
binsplot(kind='hist')/plt.hist分箱数量;本课用了 10、30、40、20,越大粒度越细但越易引入噪声
figsizeplot画布尺寸(英寸),本课统一使用 (12,12) 或默认
alphaplt.hist柱条透明度(0~1);叠加多个直方图时 0.5 可保证层次可见
label/plt.legend()plt.hist图例文字与显示,用于区分分类分组
colorplt.hist每条直方图的颜色,本课按 6 种保护状态一一指定
bw_adjustsns.kdeplot带宽调整因子(正数);越小越"欠平滑",越大越"过平滑"
huesns.kdeplot按指定列分组绘制多条密度曲线
fill/common_normsns.kdeplot是否填充;是否共享归一化基准(False 便于比较形状)
palette/linewidthsns.kdeplot分组配色板;曲线轮廓线宽(0 即无轮廓)

8. 作业、挑战与 R 语言版本

  • 课后作业:assignment.md 要求换一个数据集(例如来自 Kaggle 的数据源)自建 notebook 讲一个"故事",且必须使用直方图;评分标准(Rubric)为:优秀 = 有完整注释(含数据来源)且至少使用 5 个直方图发现数据事实;及格 = 注释不完整或有 bug;待改进 = 无注释且含 bug。
  • 课堂挑战:在网络上搜索直方图的良好使用案例,思考它们如何用直方图展示分布、应用于哪些领域。
  • 课后自修:阅读 Seabornkdeplot文档,理解"一个或多个维度上的连续概率密度曲线"这一概念。
  • R 语言版本:仓库同时提供等价的 R/ggplot2 实现,见 R 版课程,其中用geom_histogram(bins=10)coord_flip()完成同样的分布可视化流程,便于与 Python 版本对照学习。

9. 小结

本课在 Data-Science-For-Beginners 的"3-Data-Visualization"模块中承担"从量(quantity)走向分布(distribution)"的转折:

  1. 散点图能给分布一个粗略轮廓,但刻画真实分布应使用直方图;
  2. bins、布尔掩码过滤是控制直方图粒度与偏态的两个基本杠杆;hist2d用颜色密度揭示双变量联合分布的汇聚点;
  3. 分类(文本)字段通过.loc逐类提取 + 半透明叠加直方图,即可在一张图中对比多组分布;
  4. Seabornkdeplot以平滑曲线替代阶梯,bw_adjust控制平滑强度,hue/fill/common_norm组合支持分组密度对比,直至双变量多密度叠加——为第 11 课"比例可视化"与后续生命周期分析打好分布直觉基础。

【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 23:06:45

理解AI创作边界:从技术原理到应对无法生成内容的策略

简介&#xff1a;《当代中国社会阶层研究报告》是一份系统剖析1978年经济改革以来中国社会阶层结构变迁的社会学文献&#xff0c;面向社会学研究者、政策分析者及关注社会分层议题的高校师生。报告基于职业分化和组织资源、经济资源、文化技术资源占有情况&#xff0c;提出十大…

作者头像 李华
网站建设 2026/9/6 23:00:17

AI爆发:从“实验室”到“万物智能”,算力需求“指数级膨胀”

目录 一、AI爆发:从“实验室”到“万物智能”,算力需求“指数级膨胀” 二、CPU/GPU的“力不从心”:不是“不够快”,而是“不对口” 1. CPU:“串行思维”不适合AI的“并行狂欢”​ 2. GPU:“通用并行”但“功耗和成本太高”​ 三、NPU的“天生优势”:为AI神经网络“…

作者头像 李华
网站建设 2026/9/6 22:58:13

Deep-Live-Cam 快速上手:如何用 1 张照片搞定实时换脸

Deep-Live-Cam 快速上手&#xff1a;如何用 1 张照片搞定实时换脸 【免费下载链接】Deep-Live-Cam real time face swap and one-click video deepfake with only a single image 项目地址: https://gitcode.com/GitHub_Trending/de/Deep-Live-Cam Deep-Live-Cam 是一款…

作者头像 李华