查看全课大纲(第 52 / 101 节)
- 1.数据分析基本概念
- 2.学习数据分析的一般路线
- 3.数据分析的流程
- 4.数据类型
- 5.环境部署(1)
- 6.环境部署(2)
- 7.课程介绍
- 8.TXT文件操作
- 9.JSON文件操作
- 10.CSV文件操作
- 11.Excel文件操作
- 12.数据库及SQL常用语法
- 13.数据库基本操作
- 14.数据库多表连接
- 15.实战:欧洲职业足球数据库分析
- 16.爬虫简介
- 17.URL管理模块
- 18.网页下载模块
- 19.网页解析模块(1)
- 20.网页解析模块(2)
- 21.Scrapy简介
- 22.Scrapy使用步骤(1)
- 23.Scrapy使用步骤(2)
- 24.Scrapy使用步骤(3)
- 25.Scrapy使用步骤(4)
- 26.实战:获取国内城市空气质量指数数据
- 27.NumPy和SciPy介绍
- 28.多维数组
- 29.多维数组操作
- 30.NumPy的常用方法
- 31.向量化介绍
- 32.向量化及通用函数
- 33.实战:2016美国大选分析
- 34.数据结构-Series
- 35.数据结构-DataFrame
- 36.数据结构-Index
- 37.Series的索引操作
- 38.DataFrame的索引操作
- 39.索引操作总结
- 40.运算与对齐
- 41.函数应用操作(1) -- map
- 42.函数应用操作 (2) -- apply applymap
- 43.文件读写操作
- 44.排序操作
- 45.数据清洗--处理缺失数据
- 46.数据清洗--处理重复数据
- 47.数据清洗--替换数据
- 48.常用统计方法(1) -- describe quantile
- 49.常用统计方法(2) -- sum mean median count
- 50.常用统计方法(3) -- max min idxmax idxmin
- 51.常用统计方法(4) -- mad var std cumsum
- 52.实战:全球食品数据分析
- 53.层级索引
- 54.分组与聚合介绍
- 55.分组操作(1) -- GroupBy对象及常用聚合操作
- 56.分组操作(2) -- 自定义分组及聚合操作
- 57.透视表介绍
- 58.透视表操作
- 59.数据规整(1) -- 数据合并concat
- 60.数据规整(2) -- 数据连接merge
- 61.数据重构(3) -- 数据重构stack unstack
- 62.实战:互联网电影资料库分析
- 63.探索性数据分析EDA介绍
- 64.EDA的目的
- 65.EDA常用工具
- 66.Matplotlib绘图基本介绍
- 67.Matplotlib画布
- 68.散点图和柱状图的绘制
- 69.直方图的绘制
- 70.矩阵绘图
- 71.子图的使用
- 72.Matplotlib颜色、标记、线型
- 73.Matplotlib坐标刻度、标签、图例、标题
- 74.Seaborn介绍
- 75.数据集分布可视化(1) -- 单变量分布、双变量分布
- 76.数据集分布可视化(2) -- 变量关系可视化
- 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
- 78.交互式数据可视化工具Bokeh介绍
- 79.Bokeh绘制散点图、柱状图、盒子图、弦图
- 80.Bokeh绘制常用图形元素
- 81.3D绘图 -- mplot3d
- 82.3D曲线可视化
- 83.3D散点图可视化
- 84.3D柱状图可视化
- 85.Pandas绘图
- 86.实战:Lending Club借贷数据探索性分析及可视化
- 87.机器学习介绍及应用场景
- 88.机器学习建模介绍 (1) -- 分类
- 89.机器学习建模介绍 (2) -- 回归
- 90.机器学习建模介绍 (3) -- 聚类
- 91.机器学习分类
- 92.机器学习工具scikit-learn
- 93.使用scikit-learn的流程
- 94.数据集准备及划分
- 95.模型选择
- 96.数据预处理及特征工程
- 97.过拟合与欠拟合
- 98.模型调参介绍
- 99.模型调参方法
- 100.模型测试及评价
- 101.实战:通过移动设备行为数据预测性别和年龄
实战:全球食品数据分析
约 15 分钟
全球食品数据分析实战
小象实战讲义 · Python数据分析实战
在掌握了Pandas的核心数据结构与基本操作后,本节我们将通过一个完整的实战项目,将所学知识融会贯通。我们将分析一份全球食品数据,目标是计算每个国家食品中添加剂种类的平均数量。这个项目将带你体验从数据读取、清洗、处理到最终统计与输出的完整数据分析流程。
💡 核心导读
- 项目目标:分析全球食品数据,计算各国食品添加剂种类的平均数量。
- 数据处理:学习如何通过
usecols参数高效读取大型CSV文件的指定列,并进行缺失值清洗。 - 字符串向量化操作:掌握使用
.str访问器对Series中的字符串进行批量、高效的处理,如大小写转换和模式匹配。 - 数据统计与聚合:通过循环遍历国家列表,对数据进行分组统计,并计算均值。
- 结果输出:将统计分析结果保存为新的CSV文件,完成数据分析闭环。
项目概述与数据探索
我们的目标是分析一份全球食品数据集,计算出各个国家食品中添加剂种类数量的平均值。数据集以CSV格式提供,记录了不同时期、不同国家食品的各项属性,包括产品名称、国家、添加剂数量等。
由于原始数据集较大(约157MB),我们不需要读取全部列。根据分析目标,我们只关心countries_en(国家名称)和additives_n(添加剂数量)这两列。Pandas的read_csv函数允许我们通过usecols参数指定要读取的列,从而极大地节省内存和加载时间。
import pandas as pd
# 为了演示,我们在代码块内构造一个微型模拟数据集。
# 注意:实际项目中,数据来自外部CSV文件,这里仅作流程演示。
data = pd.DataFrame({
'countries_en': ['France', 'france', 'United Kingdom', 'France,Germany', 'Germany', '', 'Italy', 'united kingdom'],
'additives_n': [5.0, 3.0, 2.0, None, 4.0, 1.0, 6.0, 2.5]
})
print("原始模拟数据:")
print(data)
print("\n数据形状:", data.shape)原始模拟数据:
countries_en additives_n
0 France 5.0
1 france 3.0
2 United Kingdom 2.0
3 France,Germany NaN
4 Germany 4.0
5 1.0
6 Italy 6.0
7 united kingdom 2.5
数据形状: (8, 2)观察模拟数据,我们发现countries_en列存在大小写不一致、多个国家用逗号分隔、以及空字符串的情况。additives_n列存在缺失值(NaN)。这些都需要在分析前进行处理。
数据分析四步法
针对本项目,我们可以将分析流程归纳为四个清晰的步骤:
- 数据清洗:处理缺失值,确保用于统计的数据是有效的。
- 获取国家列表:从
countries_en列中提取出唯一、规范化的国家名称列表。 - 分组统计:针对每个国家,计算其食品添加剂数量的平均值。
- 保存结果:将统计结果保存到文件,便于后续查看或使用。
第一步:数据清洗
数据清洗的首要任务是处理缺失值。对于additives_n列,如果其为NaN,我们无法进行有效的数值计算。因此,一个直接的方法是删除additives_n为缺失值的行。
import pandas as pd
# 构造模拟数据
data = pd.DataFrame({
'countries_en': ['France', 'france', 'United Kingdom', 'France,Germany', 'Germany', '', 'Italy', 'united kingdom'],
'additives_n': [5.0, 3.0, 2.0, None, 4.0, 1.0, 6.0, 2.5]
})
# 数据清洗:删除添加剂数量为缺失值的行
data_cleaned = data.dropna(subset=['additives_n'])
print("清洗后(删除additives_n缺失行)的数据:")
print(data_cleaned)
print("\n清洗后数据形状:", data_cleaned.shape)清洗后(删除additives_n缺失行)的数据:
countries_en additives_n
0 France 5.0
1 france 3.0
2 United Kingdom 2.0
4 Germany 4.0
5 1.0
6 Italy 6.0
7 united kingdom 2.5
清洗后数据形状: (7, 2)dropna方法会返回一个删除缺失值后的新DataFrame。参数subset=['additives_n']指定只针对additives_n列检查缺失值。其他列的缺失值不影响该行的删除。
第二步:获取规范化的国家列表
我们需要从countries_en列中提取出一个干净的国家列表。这包括:
- 将国家名称统一为小写,以消除大小写差异。
- 过滤掉包含逗号(
,)的记录,因为这类记录代表多个国家,不符合我们“按单个国家统计”的目标。 - 使用
unique()方法获取唯一值列表。
Pandas的.str访问器提供了向量化的字符串操作方法,可以高效地对整个Series执行字符串处理,而无需编写循环。
import pandas as pd
# 构造清洗后的模拟数据
data_cleaned = pd.DataFrame({
'countries_en': ['France', 'france', 'United Kingdom', 'Germany', '', 'Italy', 'united kingdom'],
'additives_n': [5.0, 3.0, 2.0, 4.0, 1.0, 6.0, 2.5]
})
def get_countries(countries_series):
"""
从国家序列中提取唯一、规范化的国家列表。
参数:
countries_series: pandas Series,包含国家名称字符串。
返回:
唯一国家名称列表(小写)。
"""
# 1. 全部转换为小写
proc_series = countries_series.str.lower()
print("转换为小写后:\n", proc_series.tolist())
# 2. 去掉包含逗号(,)和空字符串的数据
# ~ 表示逻辑取反,保留不包含逗号且非空的记录
filter_condition = (~proc_series.str.contains(',')) & (proc_series != '')
proc_series = proc_series[filter_condition]
print("过滤掉含逗号和空值后:\n", proc_series.tolist())
# 3. unique()获取数据的唯一值
countries = proc_series.unique()
print(f'\n共有{len(countries)}个不同的国家: {countries}')
return countries
# 应用函数
countries_list = get_countries(data_cleaned['countries_en'])转换为小写后:
['france', 'france', 'united kingdom', 'germany', '', 'italy', 'united kingdom']
过滤掉含逗号和空值后:
['france', 'france', 'united kingdom', 'germany', 'italy', 'united kingdom']
共有4个不同的国家: <StringArray>
['france', 'united kingdom', 'germany', 'italy']
Length: 4, dtype: str第三步:按国家统计添加剂平均值
获得国家列表后,我们需要遍历每个国家,从数据中筛选出对应国家的记录,然后计算additives_n的平均值。
这里有一个关键点:我们的国家列表是小写的(如'france'),但原始数据中的countries_en列可能是任何大小写形式(如'France')。因此,在筛选时需要进行大小写不敏感的匹配。我们可以使用Series.str.contains(country, case=False)来实现。
import pandas as pd
# 构造数据和国家列表
data_df = pd.DataFrame({
'countries_en': ['France', 'france', 'United Kingdom', 'Germany', 'Italy', 'united kingdom'],
'additives_n': [5.0, 3.0, 2.0, 4.0, 6.0, 2.5]
})
countries = ['france', 'united kingdom', 'germany', 'italy']
def get_additives_count(countries, data_df):
"""
计算每个国家食品添加剂数量的平均值。
参数:
countries: 国家名称列表(小写)。
data_df: 包含`countries_en`和`additives_n`列的DataFrame。
返回:
按统计值降序排列的DataFrame,包含'country'和'count'两列。
"""
count_list = []
for country in countries:
# 大小写不敏感地筛选包含该国家名称的记录
# 注意:contains是子串匹配,对于更精确的匹配(如避免`united`匹配`united kingdom`),
# 可以使用正则表达式单词边界`\b`。此处为演示简化处理。
filtered_data = data_df[data_df['countries_en'].str.contains(country, case=False)]
# 计算该国家添加剂数量的平均值
mean_count = filtered_data['additives_n'].mean()
count_list.append(mean_count)
print(f"国家 '{country}': 匹配到 {len(filtered_data)} 条记录,平均添加剂数量 = {mean_count:.2f}")
# 构建结果DataFrame
result_df = pd.DataFrame()
result_df['country'] = countries
result_df['count'] = count_list
# 按统计值降序排序
result_df.sort_values('count', ascending=False, inplace=True)
return result_df
results = get_additives_count(countries, data_df)
print("\n最终统计结果(按平均值降序):")
print(results)国家 'france': 匹配到 2 条记录,平均添加剂数量 = 4.00
国家 'united kingdom': 匹配到 2 条记录,平均添加剂数量 = 2.25
国家 'germany': 匹配到 1 条记录,平均添加剂数量 = 4.00
国家 'italy': 匹配到 1 条记录,平均添加剂数量 = 6.00
最终统计结果(按平均值降序):
country count
3 italy 6.00
0 france 4.00
2 germany 4.00
1 united kingdom 2.25第四步:保存统计结果
最后,我们将排序后的统计结果保存到CSV文件中,方便分享或用于报告。
import pandas as pd
# 假设这是上一步得到的统计结果
result_df = pd.DataFrame({
'country': ['italy', 'france', 'germany', 'united kingdom'],
'count': [6.00, 4.00, 4.00, 2.25]
})
# 保存到CSV文件(此处为演示,实际路径请根据需求修改)
# 设置index=False以避免将行索引也写入文件
output_path = './country_additives.csv'
# 注意:在讲义环境中不实际执行文件写入,以下代码仅展示用法。
# result_df.to_csv(output_path, index=False)
print(f"统计结果将保存至: {output_path}")
print("文件内容预览:")
print(result_df.to_string(index=False))统计结果将保存至: ./country_additives.csv
文件内容预览:
country count
italy 6.00
france 4.00
germany 4.00
united kingdom 2.25项目总结与进阶思考
在本实战中,我们完成了一个从原始数据到洞察结果的完整分析流程。我们学习了如何针对性地读取数据、清洗缺失值、利用向量化字符串操作规范化数据,并通过循环分组完成了初步的统计聚合。
细心的你可能已经发现,第三步“按国家统计”中的循环遍历国家列表,本质上是一个分组(GroupBy)操作:将数据按照“国家”这个类别进行分组,然后在每个组内进行统计计算(求平均值)。在Pandas中,groupby方法正是为这种操作而设计的,它比手动循环更加简洁和高效。
例如,上述统计过程可以用一行groupby代码近似实现(需要对国家列进行类似第二步的预处理):
# 假设data_processed是经过国家列预处理(小写、拆分等)后的DataFrame
# summary = data_processed.groupby('countries_en_processed')['additives_n'].mean().sort_values(ascending=False)这正是我们下一课《Pandas高阶应用》将要深入讲解的核心内容之一。掌握groupby,你将能更加优雅和强大地处理复杂的数据分组聚合任务。
📝 动手练一练
- 概念辨析:在数据清洗步骤,我们使用了
data.dropna(subset=['additives_n'])。如果我想删除countries_en和additives_n这两列中任何一列为缺失值的行,代码应该如何修改?
👉 点击查看参考答案
将subset参数改为包含两列的列表:data.dropna(subset=['countries_en', 'additives_n'])。或者不使用subset参数,默认会删除任何列中包含缺失值的行,但这样可能会误删其他我们不在意的列有缺失的行。
- 代码改进:在
get_countries函数中,我们过滤掉了包含逗号的国家记录。如果现在需求变了,我们需要将这些多国记录拆分开,并分别计入各个国家(例如“France,Germany”需要拆成“France”和“Germany”两个独立记录参与统计),请你思考一下实现思路可能涉及哪些Pandas操作?
👉 点击查看参考答案
思路提示:
- 使用
Series.str.split(',')将包含逗号的字符串拆分成列表。 - 使用
Series.explode()方法将列表形式的每个元素拆分成独立行。例如,['France', 'Germany']会被拆成两行,其他列的值会相应复制。 - 拆分后,可能还需要用
str.strip()去除国家名称两端的空格,然后再进行小写转换和唯一值提取。
本章小结
本节通过“全球食品数据分析”实战项目,串联了Pandas数据读取、清洗、字符串处理、数据筛选与统计汇总的核心技能。你不仅完成了第一个端到端的数据分析小项目,也接触到了数据分组聚合的初步概念。
📋 行动清单
- 尝试在本地或在线环境运行本节的完整代码,理解每一步的输入与输出。
- 修改模拟数据,增加一些边缘情况(如更多空值、更复杂的多国字符串),测试代码的健壮性。
- 预习下一课内容,思考如何用
groupby操作替换本项目中的循环统计部分。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载全套课件打包(第1-5章)ZIP · 12.8MB
- 下载全套课件打包(第6-8章)ZIP · 15MB
- 下载实战数据集:AppleStore 应用商城分析ZIP · 329KB
- 下载实战数据集:女性服装电商分析ZIP · 2.8MB
- 下载Python 数据分析环境搭建指南PDF · 2MB
- 下载Scrapy 安装教程PDF · 12.7MB
- 下载附加实战项目:AppleStore 应用商城数据分析ZIP · 0.3MB · ipynb + CSV 数据
- 下载附加实战项目:银行电话营销数据分析ZIP · 0.4MB · ipynb + CSV 数据
- 下载附加实战项目:女性服装电商评论数据分析ZIP · 2.7MB · ipynb + CSV 数据
- 下载附加实战项目:美国化学学会杂志数据分析ZIP · 34.2MB · ipynb + SQLite 数据库