news 2026/9/10 20:04:50

Data-Science-For-Beginners 第 10 课:用 R 与 ggplot2 可视化数据分布(直方图与密度图实战)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Data-Science-For-Beginners 第 10 课:用 R 与 ggplot2 可视化数据分布(直方图与密度图实战)

Data-Science-For-Beginners 第 10 课:用 R 与 ggplot2 可视化数据分布(直方图与密度图实战)

【免费下载链接】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 课程《Visualizing Distributions》的 R 语言教学版本,讲解如何使用 R 的ggplot2包对明尼苏达州鸟类数据集(data/birds.csv)进行分布分析:从散点图快速概览,到直方图(含bins参数调优、子集过滤、二维直方图),再到针对文本型数据的直方图变换,以及更平滑的密度图(geom_densityadjust参数)。学完本文,你将能够用纯 R 代码复现整套分布可视化工作流,并把同一套方法论迁移到任意数值型与分类型数据集上。

课程背景与数据集说明

在上一课中,你已经通过散点图与异常值(outlier)分析了解过这份明尼苏达州鸟类数据集,包括不同鸟类类别在最大体长上的差异。本课换一个视角:不再盯住单个变量与类别的对应关系,而是观察数据沿着坐标轴是如何组织与聚集的,也就是数据的“分布”(distribution)。

课程使用同一份数据文件 data/birds.csv,该 CSV 首行带 UTF-8 BOM 头(Name,ScientificName,...),因此 R 版本在读取时必须显式声明fileEncoding="UTF-8-BOM",否则第一列列名会带有不可见字符。数据集的列结构如下:

列名含义
Name/ScientificName鸟类常用名 / 学名
Category/Order/Family/Genus分类学层级
ConservationStatus保护状态(IUCN 缩写)
MinLength/MaxLength最小 / 最大体长(cm)
MinBodyMass/MaxBodyMass最小 / 最大体重(g)
MinWingspan/MaxWingspan最小 / 最大翼展(cm)

在 R 控制台(或 RStudio)中按以下方式导入ggplot2、读取数据并去除异常值(过滤掉翼展超过 500 的记录,沿用上一课的做法):

library(ggplot2) birds <- read.csv("../../data/birds.csv", fileEncoding="UTF-8-BOM") birds_filtered <- subset(birds, MaxWingspan < 500) head(birds_filtered)

过滤后前几行数据大致如下(以丹麦语教学版表格为例,字段含义与英文原版一致):

Navn(名称)Kategori(类别)Orden(目)Familie(科)Slægt(属)BevaringsstatusMinLængdeMaxLængdeMinKropsmasseMaxKropsmasseMinVingefangMaxVingefang
0Sortbuget fløjlsandÆnder/Gæs/VandfugleAnseriformesAnatidaeDendrocygnaLC475665210207694
1Rødbrun fløjlsandÆnder/Gæs/VandfugleAnseriformesAnatidaeDendrocygnaLC455371210508593
2SnegåsÆnder/Gæs/VandfugleAnseriformesAnatidaeAnserLC647920504050135165
3Ross' gåsAnser rossiiAnseriformesAnatidaeAnserLC57.36410661567113116
4Stor hvidkindet gåsAnser albifronsAnseriformesAnatidaeAnserLC648119303310130165

用散点图快速概览分布

在进入正式分布图表之前,可以先沿用上一课的散点图对“体长 × 目”的关系做快速侦察。R 版课程使用geom_point()+coord_flip()把目名称翻转到横轴,便于阅读:

ggplot(data=birds_filtered, aes(x=Order, y=MaxLength, group=1)) + geom_point() + ggtitle("Max Length per order") + coord_flip()

这张图能给出每个鸟目体长分布的大致范围,但它并不是展示“真实分布”的最优方式——点与点之间没有聚合信息,肉眼难以判断哪个区间的样本更密集。处理分布问题的标准工具是直方图(Histogram)

直方图:数值型数据的分布利器

ggplot2对直方图提供了非常成熟的实现:geom_histogram()会把连续数值轴切分成若干小区间(bin),用柱子的高低反映每个区间内的样本频数,形状上类似柱状图,但表达的是“数据在轴上如何聚集”。

直方图只接受数值型数据。第一个例子针对MaxBodyMass(最大体重)绘制整份数据集的分布,bins=10表示把数据切成 10 个区间:

ggplot(data = birds_filtered, aes(x = MaxBodyMass)) + geom_histogram(bins=10) + ylab('Frequency')

可以看到:数据集中 400+ 只鸟的最大体重绝大多数落在 2000 以下,呈现明显的右偏(长尾)形态——这正是生物体重数据常见的分布特征。右尾由少数大体重鸟类(如天鹅、猛禽)拉长。

调整 bins 参数提升分辨率

bins从 10 提高到 30,直方图会展示更细粒度的信息:

ggplot(data = birds_filtered, aes(x = MaxBodyMass)) + geom_histogram(bins=30) + ylab('Frequency')

参数说明:bins决定区间数量。值越小柱子越粗、分布越平滑但信息越少;值越大柱子越细、细节越丰富但也更容易暴露噪声。可以把它理解成数据聚合的“分辨率”旋钮。

通过子集过滤消除左偏

上面的直方图整体向左偏(长尾在右侧)。想要得到一个不那么偏斜、更“居中”的分布,可以在绘图前先用subset()圈定数据范围——例如只保留最大体重介于 1 与 60 之间的鸟类,再以 30 个 bin 绘图:

birds_filtered_1 <- subset(birds_filtered, MaxBodyMass > 1 & MaxBodyMass < 60) ggplot(data = birds_filtered_1, aes(x = MaxBodyMass)) + geom_histogram(bins=30) + ylab('Frequency')

✅ 动手试试:换用其他过滤条件(如MinLengthMaxWingspan)和数据范围;如果想看数据的完整分布形态,也可以去掉体重过滤条件,只保留bins设置。

二维直方图:同时观察两个分布的收敛

直方图同样支持二维扩展:geom_bin2d()把平面切成网格,用颜色深浅表示每个格子里样本的密度,scale_fill_continuous()可以指定配色方案(示例使用viridis,一种对色觉障碍友好的渐变色):

ggplot(data=birds_filtered_1, aes(x=MaxBodyMass, y=MaxLength)) + geom_bin2d() + scale_fill_continuous(type = "viridis")

结果显示体重与体长沿一条预期中的正向轴存在相关关系,并且在某个区间存在一个特别强的收敛点(颜色最亮的方格)。这种“亮点”往往提示数据的聚集中心,是探索两个变量联合分布时非常直观的起点。

文本型数据的分布:保护状态变换实战

直方图天然适合数值型数据;当需要按文本类别观察分布时,必须先做数据变换。本数据集的ConservationStatus列记录了鸟类的保护状态,缩写来自 IUCN Red List Categories(国际自然保护联盟红色名录):

  • CR:极度濒危(Critically Endangered)
  • EN:濒危(Endangered)
  • EX:灭绝(Extinct)
  • LC:无危(Least Concern)
  • NT:近危(Near Threatened)
  • VU:易危(Vulnerable)

这些是文本值,直接传给geom_histogram会失败。R 版课程的思路是:先把各状态重编码为有序数值标签x1x6),再以MinWingspan为横轴、以重编码后的状态为填充色,绘制重叠直方图position = "identity"让不同状态的柱子互相叠放而不堆叠,alpha = 0.4提供半透明效果以便观察重叠区域:

birds_filtered_1$ConservationStatus[birds_filtered_1$ConservationStatus == 'EX'] <- 'x1' birds_filtered_1$ConservationStatus[birds_filtered_1$ConservationStatus == 'CR'] <- 'x2' birds_filtered_1$ConservationStatus[birds_filtered_1$ConservationStatus == 'EN'] <- 'x3' birds_filtered_1$ConservationStatus[birds_filtered_1$ConservationStatus == 'NT'] <- 'x4' birds_filtered_1$ConservationStatus[birds_filtered_1$ConservationStatus == 'VU'] <- 'x5' birds_filtered_1$ConservationStatus[birds_filtered_1$ConservationStatus == 'LC'] <- 'x6' ggplot(data=birds_filtered_1, aes(x = MinWingspan, fill = ConservationStatus)) + geom_histogram(position = "identity", alpha = 0.4, bins = 20) + scale_fill_manual(name="Conservation Status", values=c("red","green","blue","pink"), labels=c("Endangered","Near Threatened","Vulnerable","Least Concern"))

参数说明:scale_fill_manual()name设置图例标题,values指定每个级别的填充色,labels覆盖图例显示文本。注意示例代码中values只有 4 个颜色、labels也只对应 4 个状态,而实际数据里仍存在 6 个级别(其中部分级别在过滤后的子集中没有样本或样本过少),这是 R 教学示例中常见的数据情况,不影响理解机制。

从图中看,最小翼展与保护状态之间并没有表现出明显的相关性。你可以用同样的方法测试数据集里的其他字段(如MaxLengthMaxBodyMass),也可以更换过滤条件,观察是否能找到更显著的关联。

密度图:平滑的分布曲线

细心的读者会发现,直方图是“阶梯状”的(柱子之间有明确的边界),曲线无法平滑地连成弧线。当需要展示更光滑的分布形态时,应改用密度图(density plot)

最小翼展的密度图只需一行几何对象:

ggplot(data = birds_filtered_1, aes(x = MinWingspan)) + geom_density()

这张图与之前MinWingspan的直方图形状一致,只是曲线化、平滑化了——它本质上是用核密度估计(KDE)把离散频数拟合成连续概率密度曲线。

之前那张锯齿感很强的MaxBodyMass直方图,同样可以平滑化:

ggplot(data = birds_filtered_1, aes(x = MaxBodyMass)) + geom_density()

adjust 参数:控制平滑程度

如果觉得曲线“过于平滑”而丢失了细节,可以修改adjust参数。adjust是带宽的缩放因子:值小于 1 会让带宽变窄、曲线更贴近原始数据(更粗糙),值大于 1 会让曲线更平滑。例如adjust = 1/5得到一条光滑但保留了较多起伏的曲线:

ggplot(data = birds_filtered_1, aes(x = MaxBodyMass)) + geom_density(adjust = 1/5)

✅ 建议进一步阅读geom_density()的全部可用参数(如kernelbwalphafill),并动手实验不同取值对曲线形态的影响。

按类别分组的密度图

密度图非常擅长“以极少量代码产出解释力极强的图”。例如只需三行代码,就能按鸟目(Order)分别绘制最大体重的密度曲线,fill = Order自动分组上色,alpha = 0.5控制透明度让重叠区域可见:

ggplot(data=birds_filtered_1, aes(x = MaxBodyMass, fill = Order)) + geom_density(alpha=0.5)

此时各鸟目的体重分布曲线一目了然——哪些目集中在低体重区间、哪些目明显更“重”,以及不同目之间的分布重叠程度,都能直观读出。这正是密度图相对直方图的独特优势:多组比较时更不易杂乱、更易解读。

课程延伸:挑战、自学与作业

  • 挑战(🚀 Challenge):直方图是比基础散点图、柱状图、折线图更高级的图表类型。请上网搜索优秀的直方图应用案例,思考它们被用在哪些领域、能说明什么问题。这类图表在生物学、经济学、质量控制、图像处理等需要刻画“单变量分布”的场景中非常普遍。
  • 自学(Review & Self Study):本课围绕ggplot2展开,接下来可以研究geom_density_2d()——官方将其描述为“一个或多个维度上的连续概率密度曲线”。它可以把密度估计扩展到二维平面(等高线形式),与二维直方图形成互补。
  • 作业(Assignment):本课配套作业(丹麦语版见 translations/da/3-Data-Visualization/R/10-visualization-distributions/assignment.md,英文版见 3-Data-Visualization/R/10-visualization-distributions/assignment.md)要求:从 Kaggle 等平台另选一份数据集,编写一个带完整注释的 R 脚本,围绕该数据集讲一个故事,并至少使用 5 个直方图来支撑你的发现(优秀标准还包括注明数据来源)。

与本仓库其他资源的关系

本课是 Data-Science-For-Beginners 课程第三模块“数据可视化”的一部分,同一主题在仓库中还有两个并行版本可供对照学习:

  • Python 版:3-Data-Visualization/10-visualization-distributions/README.md 使用 Pandas + Matplotlib(plot(kind='hist'))实现相同分析,并在密度图部分引入 Seaborn 的kdeplot()(对应 R 版的geom_density(),平滑参数bw_adjust对应 R 版的adjust);
  • R 版英文原稿:3-Data-Visualization/R/10-visualization-distributions/README.md 即本文所讲解文档的原始版本。

R 版课程目录下还提供了与本文每张示意图对应的 PNG 源图(3-Data-Visualization/R/10-visualization-distributions/images/),以及丹麦语译文使用的 webp 版本(translated_images/da/),便于对照图表细节。整个课程模块还配套了在线测验应用(见 quiz-app/)与手绘速记图(见 sketchnotes/10-Visualizing-Distributions.png),可以作为课前课后复习的补充材料。

至此,你已经掌握了从散点概览、直方图调参、子集过滤、二维直方图,到文本数据变换与密度图平滑的完整分布分析工具箱——下一步,就把这套流程用到你自己的数据上吧。

【免费下载链接】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/10 20:04:18

如何用telegram-bot打造高效聊天助手?从安装到精通的完整教程

如何用telegram-bot打造高效聊天助手&#xff1f;从安装到精通的完整教程 telegram-bot是一款基于插件的Telegram聊天机器人&#xff0c;能够帮助用户打造高效的聊天助手。通过简单的安装和配置&#xff0c;你可以快速拥有一个功能丰富的机器人&#xff0c;满足日常聊天、信息查…

作者头像 李华
网站建设 2026/9/10 20:02:57

电机驱动中IGBT选型的三维决策模型:电压、电流与热设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 20:01:26

Vue组件封装指南:属性、事件、插槽与方法的透传全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 20:01:04

短视频引流的卖家:流量来了,链接还没上

短视频引流的卖家&#xff1a;流量来了&#xff0c;链接还没上 一个短视频卖家的窘境&#xff1a; 「视频爆了&#xff01;一夜之间几十万播放&#xff0c;评论区全是『在哪买』。我火急火燎去上链接——结果越急越出错&#xff1a;属性填错、图片传歪、还赶上验证连环弹。等我…

作者头像 李华