Data Science for Beginners 第 09 课作业精解:用折线图、散点图与柱状图讲一个雪雁(Snegæs)的数据故事
【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners
本文基于仓库中丹麦语课程作业 translations/da/3-Data-Visualization/09-visualization-quantities/assignment.md 展开,带你完整走一遍"数据可视化讲量(Visualizing Quantities)"的作业要求:以仓库自带的数据集 data/birds.csv 为素材,用 Pandas + Matplotlib 的折线图、散点图、柱状图三种图表类型,围绕某一种鸟(原文示例为雪雁 Snegæs)构建一个有注释、有叙事、有吸引力图表的 Notebook,并按仓库给出的评分量表自查成果。
一、作业任务:从"会画图"到"讲故事"
原文作业(assignment.md)的指令原文是:
I denne lektion arbejdede du med linjediagrammer, spredningsdiagrammer og søjlediagrammer for at vise interessante fakta om dette datasæt. I denne opgave skal du dykke dybere ned i datasættet for at opdage en fakta om en given type fugl. For eksempel kan du oprette en notebook, der visualiserer alle de interessante data, du kan finde om Snegæs. Brug de tre nævnte diagramtyper til at fortælle en historie i din notebook.
中文含义:本课时你使用折线图、散点图与柱状图展示了数据集的有趣事实;本作业要求你深入挖掘数据集,发现某一类鸟的事实。作业给出的示例方向是:创建一个 Notebook,把你能找到的关于**雪雁(Snegæs / Snow goose)**的所有有趣数据可视化出来,并用上述三种图表类型在 Notebook 中"讲述一个故事"。
因此,完成本作业的技术能力清单是:
- 会用
pd.read_csv加载并检查birds.csv这类"文本 + 数值"混合结构的数据集; - 能用折线图(line plot)快速发现量级异常(离群值);
- 能用带条件标注的散点图(labeled scatter)把异常点"点名",再用行级过滤剔除噪声;
- 能用堆叠柱状图 / 水平柱状图做分组计数与组内比较;
- 能把以上步骤组织成有叙事顺序的 Notebook,并对照仓库评分量表自检。
对应的完整课时讲义见 translations/da/3-Data-Visualization/09-visualization-quantities/README.md(英文原版在 3-Data-Visualization/09-visualization-quantities/README.md),参考实现见 translations/da/3-Data-Visualization/09-visualization-quantities/solution/notebook.ipynb。
二、数据基础:birds.csv 的结构与雪雁记录
课时强调:数据存放在仓库根目录的/data文件夹下,文件为 data/birds.csv。该文件共 443 行记录(不含表头),13 列,表头如下(英文原列名 + 丹麦语讲义中的译名):
| 英文列名 | 丹麦语讲义列名 | 类型 | 说明 |
|---|---|---|---|
| Name | Navn | 文本 | 鸟的英文名,如Snow goose |
| ScientificName | VidenskabeligtNavn | 文本 | 学名,如Anser caerulescens |
| Category | Kategori | 文本 | 粗粒度类别,如Ducks/Geese/Waterfowl |
| Order | Orden | 文本 | 目,如Anseriformes |
| Family | Familie | 文本 | 科,如Anatidae |
| Genus | Slægt | 文本 | 属,如Anser |
| ConservationStatus | Bevaringsstatus | 文本 | 保护等级,如LC |
| MinLength / MaxLength | MinLængde / MaxLængde | 数值 | 体长范围(cm) |
| MinBodyMass / MaxBodyMass | MinKropsmasse / MaxKropsmasse | 数值 | 体重范围(g) |
| MinWingspan / MaxWingspan | MinVingefang / MaxVingefang | 数值 | 翼展范围(cm) |
按"围绕雪雁讲故事"的作业要求,先把与它直接相关的事实定位出来。从 data/birds.csv 中可以确认:
- 雪雁
Snow goose, Anser caerulescens:Category 为Ducks/Geese/Waterfowl,Order 为Anseriformes,Family 为Anatidae,Genus 为Anser,保护等级LC(Least Concern),体长 64–79 cm,体重 2050–4050 g,翼展 135–165 cm; - 同属(
Genus == 'Anser')的鸟在数据集中共有 3 种:雪雁(Snow goose)、Ross's goose(Anser rossii,翼展 113–116 cm)、Greater white-fronted goose(Anser albifrons,翼展 130–165 cm)——这是做"同类比较"图表的天然素材; - 数据集共 60 个 Category,其中
Ducks/Geese/Waterfowl以 45 种居首(与课时中"Minnesota 是万湖之地,水禽最多"的结论一致); - ConservationStatus 分布为:LC 402、NT 27、VU 10、EN 2、CR 1、EX 1——"有多少种濒危/受胁鸟"正是讲义列出的可用柱状图回答的 mængde(量)问题之一。
加载数据与快速检查(作业 Notebook 的第一组单元格):
import pandas as pd import matplotlib.pyplot as plt birds = pd.read_csv('../../data/birds.csv') # 相对课时文件夹的路径;若在 solution 子目录则为 '../../../data/birds.csv' birds.head()这些数据是文本与数值的混合体,这也是为什么后面所有可视化都要显式选择数值列(MinLength、MaxWingspan等)或分组计数列。
三、步骤 1:折线图定位量级异常(linjediagram)
讲义的核心工作流是:识别要关注的 dataframe 列 → 做必要变换 → 分配 x/y 轴 → 选择图表类型 → 显示。折线图是"先看全貌"的最佳起点,因为一条连续的线会立刻暴露量级跳变。
最简折线图(直接复用 Series.plot):
wingspan = birds['MaxWingspan'] wingspan.plot()运行后你会立刻看到一个约 2300 厘米(23 米)的巨大尖峰——讲义原话是"难道密歇根上空飞着翼龙(Pterodactyls)?"。此时不要跳出去用 Excel 排序,而是继续在图上工作。
给 x 轴加鸟类名称标签:
plt.title('Max Wingspan in Centimeters') plt.ylabel('Wingspan (CM)') plt.xlabel('Birds') plt.xticks(rotation=45) x = birds['Name'] y = birds['MaxWingspan'] plt.plot(x, y) plt.show()但 443 只鸟全标注后,即使旋转 45 度也密密麻麻不可读。讲义的解法是:换成散点图制造空间,只给离群点标注——
plt.title('Max Wingspan in Centimeters') plt.ylabel('Wingspan (CM)') plt.tick_params(axis='both', which='both', labelbottom=False, bottom=False) for i in range(len(birds)): x = birds['Name'][i] y = birds['MaxWingspan'][i] plt.plot(x, y, 'bo') if birds['MaxWingspan'][i] > 500: plt.text(x, y * (1 - 0.05), birds['Name'][i], fontsize=12) plt.show()逐行解读(讲义有明确解释,这里保留其因果链):
plt.tick_params(..., labelbottom=False, bottom=False):隐藏底部刻度标签,给图内标注腾出空间;- 循环内
plt.plot(x, y, 'bo'):bo是"蓝色圆点"(blue + circle)的绘图格式符,用散点代替折线,点与点不再相连,视觉上更宽松; if birds['MaxWingspan'][i] > 500:只对翼展超过 500 cm 的鸟执行plt.text标注;y * (1 - 0.05):把标签沿 y 轴下移 5%,避免标签与点重叠。
从 data/birds.csv 可核实,全表中MaxWingspan > 500的记录恰好只有两条:
| Name | MaxWingspan (cm) |
|---|---|
| Bald eagle | 2300 |
| Prairie falcon | 1100 |
讲义的判断是:白头海雕(Bald eagle)与草原隼(Prairie falcon)大概率是录入时多打了一个0(多补一个 0 的笔误)。
四、步骤 2:过滤离群值,得到更一致的散点图(spredningsdiagram)
识别出异常后,讲义选择在绘图循环里直接跳过这两行,而不修改原始 dataframe:
plt.title('Max Wingspan in Centimeters') plt.ylabel('Wingspan (CM)') plt.xlabel('Birds') plt.tick_params(axis='both', which='both', labelbottom=False, bottom=False) for i in range(len(birds)): x = birds['Name'][i] y = birds['MaxWingspan'][i] if birds['Name'][i] not in ['Bald eagle', 'Prairie falcon']: plt.plot(x, y, 'bo') plt.show()讲义明确给出了三种等价的替代处理,供你按作业需求选择:
- 在后续图表中过滤掉这两只离群鸟(上面的写法);
- 修正它们翼展的笔误(如把 2300 改为 230 量级的值);
- 对不依赖翼展字段的练习(例如按 Category 的柱状图),原样保留也不影响。
过滤后数据"more coherent and understandable"(更一致、可读)。对作业的建议:在讲雪雁的故事时,把"发现 2300 cm 尖峰 → 用条件标注点名 → 过滤后重画"这一段完整保留,它本身就是"用图表做数据准备(data preparation)"的叙事高光,也是评分标准中"solid historiefortælling"(扎实的叙事)的直接得分点。
五、步骤 3:柱状图做分组计数与比较(søjlediagram)
讲义列出了本数据集可以直接用"量"图表回答的三个问题,全部是柱状图的地盘:
- Hvor mange kategorier af fugle er der, og hvad er deres antal?(有多少类鸟?各自多少?)
- Hvor mange fugle er uddøde, truede, sjældne eller almindelige?(多少种灭绝、受胁、稀有或常见?)
- Hvor mange er der af de forskellige slægter og ordener?(各属、各目各有多少?)
从原始数据直接堆叠柱状图(讲义演示的"反面教材",用于说明为什么必须先聚合):
birds.plot(x='Category', kind='bar', stacked=True, title='Birds of Minnesota')这张图不可读——443 行原始记录在 60 个类别上堆叠,视觉上无法区分。结论是:柱状图要画"聚合后的量"。
按类别计数的水平柱状图:
category_count = birds.value_counts(birds['Category'].values, sort=True) plt.rcParams['figure.figsize'] = [6, 12] # 60 个类别太多,纵向加高 category_count.plot.barh()注意讲义的分工表述:"Pandas 管理数据,Matplotlib 负责画图"——value_counts(..., sort=True)完成分组计数与排序,plot.barh()只负责渲染。运行结果中,最长的柱子是Ducks/Geese/Waterfowl(45 种),其次是New World warblers(41 种)与Sandpipers/Allies(34 种)。
组间比较:每类鸟的 MaxLength。用plt.barh(y=..., width=...)显式指定坐标:
maxLength = birds['MaxLength'] plt.barh(y=birds['Category'], width=maxLength) plt.rcParams['figure.figsize'] = [6, 12] plt.show()结果符合常识:蜂鸟(Hummingbirds)最短,鹈鹕(Pelicans)、大鹅最长——讲义点评:"数据讲得通,就是好事"。
组内叠加:Min 与 Max 长度叠在同一组。这是本课最有信息量的一张柱状图,把"每个类别的长度区间"画成两根叠加的水平条:
minLength = birds['MinLength'] maxLength = birds['MaxLength'] category = birds['Category'] plt.barh(category, maxLength) plt.barh(category, minLength) # 短条叠在长条之上,形成区间带 plt.show()从源码结构看,这两次barh调用共享同一组 y 轴类别,先画最大长度、再画最小长度,视觉上就得到"每类鸟的最小–最大长度带"。讲义的结论:鸟越大,其长度跨度(max−min)也越大。
图表选型速查(讲义 ✅ 清单,完整继承)
- 分析随时间的趋势:折线(linje)
- 比较数值:柱形、条形、饼图、散点(søjle, kolonne, cirkel, scatterplot)
- 显示部分与整体的关系:饼图(cirkel)
- 显示数据分布:散点、柱形(scatterplot, søjle)
- 显示趋势:折线、条形(linje, kolonne)
- 显示数值间的关系:折线、散点、气泡(linje, scatterplot, boble)
六、作业实战:为雪雁(Snegæs)搭一个三图故事 Notebook
下面把上述三步组织成作业要求的"故事线",并给出可直接运行的参考代码(相对路径按你放 Notebook 的位置调整;若在solution/子目录中,用../../../data/birds.csv)。
第一幕:它有多大的翅膀?(折线图 → 散点图)
import pandas as pd import matplotlib.pyplot as plt birds = pd.read_csv('../../data/birds.csv') # 1) 全量 MaxWingspan 折线图:一眼看到 2300 cm 的量级异常 birds['MaxWingspan'].plot() plt.ylabel('MaxWingspan (cm)') plt.title('Max Wingspan of Minnesota Birds') plt.show() # 2) 只标注 > 500 cm 的离群点(数据中即 Bald eagle 与 Prairie falcon) plt.tick_params(axis='both', which='both', labelbottom=False, bottom=False) for i in range(len(birds)): plt.plot(birds['Name'][i], birds['MaxWingspan'][i], 'bo') if birds['MaxWingspan'][i] > 500: plt.text(birds['Name'][i], birds['MaxWingspan'][i] * 0.95, birds['Name'][i], fontsize=12) plt.title('Outliers in Max Wingspan') plt.ylabel('Wingspan (cm)') plt.show()第二幕:它在雁属(Anser)里处于什么位置?(柱状图/条形图比较)
anser = birds[birds['Genus'] == 'Anser'] # Snow goose / Ross's goose / Greater white-fronted goose # 双条形比较翼展区间:先画 MaxWingspan,再叠 MinWingspan plt.barh(anser['Name'], anser['MaxWingspan']) plt.barh(anser['Name'], anser['MinWingspan']) plt.xlabel('Wingspan (cm)') plt.title('Wingspan Range in Genus Anser') plt.show() # 体重区间同理 plt.barh(anser['Name'], anser['MaxBodyMass']) plt.barh(anser['Name'], anser['MinBodyMass']) plt.xlabel('Body Mass (g)') plt.title('Body Mass Range in Genus Anser') plt.show()结合 data/birds.csv 中的真实数值可以预期:雪雁的翼展区间(135–165 cm)与 Greater white-fronted goose(130–165 cm)几乎持平,但雪雁的体重区间(2050–4050 g)明显重于另外两种(Ross's goose 1066–1567 g、Greater white-fronted goose 1930–3310 g),这就是"同属比较"能讲出的第一层故事。
第三幕:它所处的生态系统有多"水"?(分组计数柱状图 + 保护状态)
# 雪雁所属类别在数据集中的体量 category_count = birds.value_counts(birds['Category'].values, sort=True) plt.rcParams['figure.figsize'] = [6, 12] category_count.plot.barh() plt.title('Bird Counts by Category in Minnesota Dataset') plt.show() # 保护状态计数(讲义 mængde 问题之一) status_count = birds.value_counts(birds['ConservationStatus'].values, sort=True) status_count.plot.bar() plt.title('Conservation Status Counts') plt.ylabel('Species') plt.show()可预期的数字:Ducks/Geese/Waterfowl45 种居 60 类之首;保护状态合计 LC 402、NT 27、VU 10、EN 2、CR 1、EX 1——"绝大多数物种是 LC,雪雁也不例外"就是第三幕的落点。
叙事与注释要求:评分量表明确要求"godе kommentarer"(好的注释)。每个单元格前应有一段 Markdown 说明"这张图要回答什么问题、图里看到了什么",例如:
Dette linjediagram viser MaxWingspan for alle 443 fugle. Den markante spids ved ca. 2300 cm peger på sandsynligvis to tastefejl (Bald eagle, Prairie falcon), som filtreres væk i næste celle.中文:本折线图展示全部 443 种鸟的 MaxWingspan,约 2300 cm 的尖峰大概率是两条录入笔误,下一单元格将其过滤。
七、评分量表(Bedømmelseskriterier)
作业文档给出了三档量表,完整继承如下(丹麦语原文 + 中文对照):
| Eksemplarisk(优秀) | Tilstrækkelig(合格) | Kræver Forbedring(需改进) |
|---|---|---|
| En notebook præsenteres med gode kommentarer, solid historiefortælling og attraktive grafer —— 提交了带良好注释、扎实叙事和美观图表的 Notebook | Notebooken mangler ét af disse elementer —— Notebook 缺少其中一项 | Notebooken mangler to af disse elementer —— Notebook 缺少其中两项 |
自查清单(对照"优秀"档):
- Notebook 三种图表类型(折线、散点、柱状)全部出现,且各服务于叙事的一环;
- 每个图表前有 Markdown 注释说明意图,图中结论用文字复述;
- 离群值处理过程(发现 → 标注 → 过滤)在 Notebook 中留痕;
- 图表带标题与坐标轴标签(
plt.title/plt.xlabel/plt.ylabel); - 至少一处"从数据中读出的新事实"(例如雪雁体重区间在 Anser 属内最大)。
八、延伸挑战与自检路径
讲义的 🚀 Udfordring(挑战)建议:本数据集只是"某一生态系统中各类鸟"的一个样本,可另行寻找其他鸟类数据集,重复"折线找异常 → 散点点名 → 柱状图分组"的流程,练习从新数据中发现未知事实。
仓库内可以继续深入的路径:
- 课时讲义(丹麦语 / 英语):translations/da/3-Data-Visualization/09-visualization-quantities/README.md、3-Data-Visualization/09-visualization-quantities/README.md;
- 作业参考实现:translations/da/3-Data-Visualization/09-visualization-quantities/solution/notebook.ipynb(英文版在 3-Data-Visualization/09-visualization-quantities/solution/);
- 后续课时可把同样的"量"思维迁移到分布与比例可视化:3-Data-Visualization/10-visualization-distributions/README.md、3-Data-Visualization/11-visualization-proportions/README.md;
- 讲义还提示了仓库未覆盖的替代库 Plotly,可作课外扩展阅读。
适用前提与限制:上述所有代码依赖 Python 环境中的pandas与matplotlib(参考 Notebook 的 kernelspec 标注为 Python 3.7 量级的解释器,实际任意支持这两个库的 Python 3 版本均可);birds.csv中的列名与数值以当前仓库 data/birds.csv 的实际内容为准,若上游数据更新,离群值与计数结果需重新核实。
【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考