查看全课大纲(第 52 / 101 节)
  1. 1.数据分析基本概念
  2. 2.学习数据分析的一般路线
  3. 3.数据分析的流程
  4. 4.数据类型
  5. 5.环境部署(1)
  6. 6.环境部署(2)
  7. 7.课程介绍
  8. 8.TXT文件操作
  9. 9.JSON文件操作
  10. 10.CSV文件操作
  11. 11.Excel文件操作
  12. 12.数据库及SQL常用语法
  13. 13.数据库基本操作
  14. 14.数据库多表连接
  15. 15.实战:欧洲职业足球数据库分析
  16. 16.爬虫简介
  17. 17.URL管理模块
  18. 18.网页下载模块
  19. 19.网页解析模块(1)
  20. 20.网页解析模块(2)
  21. 21.Scrapy简介
  22. 22.Scrapy使用步骤(1)
  23. 23.Scrapy使用步骤(2)
  24. 24.Scrapy使用步骤(3)
  25. 25.Scrapy使用步骤(4)
  26. 26.实战:获取国内城市空气质量指数数据
  27. 27.NumPy和SciPy介绍
  28. 28.多维数组
  29. 29.多维数组操作
  30. 30.NumPy的常用方法
  31. 31.向量化介绍
  32. 32.向量化及通用函数
  33. 33.实战:2016美国大选分析
  34. 34.数据结构-Series
  35. 35.数据结构-DataFrame
  36. 36.数据结构-Index
  37. 37.Series的索引操作
  38. 38.DataFrame的索引操作
  39. 39.索引操作总结
  40. 40.运算与对齐
  41. 41.函数应用操作(1) -- map
  42. 42.函数应用操作 (2) -- apply applymap
  43. 43.文件读写操作
  44. 44.排序操作
  45. 45.数据清洗--处理缺失数据
  46. 46.数据清洗--处理重复数据
  47. 47.数据清洗--替换数据
  48. 48.常用统计方法(1) -- describe quantile
  49. 49.常用统计方法(2) -- sum mean median count
  50. 50.常用统计方法(3) -- max min idxmax idxmin
  51. 51.常用统计方法(4) -- mad var std cumsum
  52. 52.实战:全球食品数据分析
  53. 53.层级索引
  54. 54.分组与聚合介绍
  55. 55.分组操作(1) -- GroupBy对象及常用聚合操作
  56. 56.分组操作(2) -- 自定义分组及聚合操作
  57. 57.透视表介绍
  58. 58.透视表操作
  59. 59.数据规整(1) -- 数据合并concat
  60. 60.数据规整(2) -- 数据连接merge
  61. 61.数据重构(3) -- 数据重构stack unstack
  62. 62.实战:互联网电影资料库分析
  63. 63.探索性数据分析EDA介绍
  64. 64.EDA的目的
  65. 65.EDA常用工具
  66. 66.Matplotlib绘图基本介绍
  67. 67.Matplotlib画布
  68. 68.散点图和柱状图的绘制
  69. 69.直方图的绘制
  70. 70.矩阵绘图
  71. 71.子图的使用
  72. 72.Matplotlib颜色、标记、线型
  73. 73.Matplotlib坐标刻度、标签、图例、标题
  74. 74.Seaborn介绍
  75. 75.数据集分布可视化(1) -- 单变量分布、双变量分布
  76. 76.数据集分布可视化(2) -- 变量关系可视化
  77. 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
  78. 78.交互式数据可视化工具Bokeh介绍
  79. 79.Bokeh绘制散点图、柱状图、盒子图、弦图
  80. 80.Bokeh绘制常用图形元素
  81. 81.3D绘图 -- mplot3d
  82. 82.3D曲线可视化
  83. 83.3D散点图可视化
  84. 84.3D柱状图可视化
  85. 85.Pandas绘图
  86. 86.实战:Lending Club借贷数据探索性分析及可视化
  87. 87.机器学习介绍及应用场景
  88. 88.机器学习建模介绍 (1) -- 分类
  89. 89.机器学习建模介绍 (2) -- 回归
  90. 90.机器学习建模介绍 (3) -- 聚类
  91. 91.机器学习分类
  92. 92.机器学习工具scikit-learn
  93. 93.使用scikit-learn的流程
  94. 94.数据集准备及划分
  95. 95.模型选择
  96. 96.数据预处理及特征工程
  97. 97.过拟合与欠拟合
  98. 98.模型调参介绍
  99. 99.模型调参方法
  100. 100.模型测试及评价
  101. 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)。这些都需要在分析前进行处理。

数据分析四步法

针对本项目,我们可以将分析流程归纳为四个清晰的步骤:

  1. 数据清洗:处理缺失值,确保用于统计的数据是有效的。
  2. 获取国家列表:从countries_en列中提取出唯一、规范化的国家名称列表。
  3. 分组统计:针对每个国家,计算其食品添加剂数量的平均值。
  4. 保存结果:将统计结果保存到文件,便于后续查看或使用。

第一步:数据清洗

数据清洗的首要任务是处理缺失值。对于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列中提取出一个干净的国家列表。这包括:

  1. 将国家名称统一为小写,以消除大小写差异。
  2. 过滤掉包含逗号(,)的记录,因为这类记录代表多个国家,不符合我们“按单个国家统计”的目标。
  3. 使用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,你将能更加优雅和强大地处理复杂的数据分组聚合任务。

📝 动手练一练

  1. 概念辨析:在数据清洗步骤,我们使用了data.dropna(subset=['additives_n'])。如果我想删除countries_en和additives_n这两列中任何一列为缺失值的行,代码应该如何修改?
👉 点击查看参考答案

将subset参数改为包含两列的列表:data.dropna(subset=['countries_en', 'additives_n'])。或者不使用subset参数,默认会删除任何列中包含缺失值的行,但这样可能会误删其他我们不在意的列有缺失的行。

  1. 代码改进:在get_countries函数中,我们过滤掉了包含逗号的国家记录。如果现在需求变了,我们需要将这些多国记录拆分开,并分别计入各个国家(例如“France,Germany”需要拆成“France”和“Germany”两个独立记录参与统计),请你思考一下实现思路可能涉及哪些Pandas操作?
👉 点击查看参考答案

思路提示:

  1. 使用Series.str.split(',')将包含逗号的字符串拆分成列表。
  2. 使用Series.explode()方法将列表形式的每个元素拆分成独立行。例如,['France', 'Germany']会被拆成两行,其他列的值会相应复制。
  3. 拆分后,可能还需要用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 数据库
    下载