跳转至

15.2 数据处理与可视化:Pandas 数据处理

内容梗概

本课介绍 Python 数据分析领域事实上的标准库 Pandas。老师先对比 MATLAB 说明 Pandas + Matplotlib 是开源免费的数据处理与画图组合,随后讲解 Pandas 看待数据的方式:两个核心数据类型 Series(一列数据)和 DataFrame(由多个 Series 拼成的表格)。课上在虚拟环境中安装 pandas,演示了 read_csv/read_excel 载入数据,Series 与 DataFrame 的多种创建方式,用 loc/iloc 查看和选择数据、条件筛选、at/iat 精确赋值,以及 dropna/fillna 处理无效数据。老师同时补充了 Pandas 基于 NumPy 的背景知识。

知识点详解

为什么用 Pandas(约 00:00 - 05:30)

  • 上节课的 csv/openpyxl 只适合"打开表格用一用"的简单场景;要做趋势分析、线性回归等数据处理,需要更专业的工具。
  • 最有名的科学计算工具是 MATLAB,但收费;Python 中用 Pandas 处理数据 + Matplotlib 画图,开源免费,大部分场景够用。
  • Pandas 的好处:提供非常完善的接口,能把各种类型/来源的数据统一载入为表格(或更高维矩阵)形式再处理。官方文档的 IO tools 支持读取 CSV、text、JSON、HTML、Excel、剪贴板、HDF5 等各种数据来源。
  • 在 Python 数据分析领域 Pandas 基本没有竞争对手(不像爬虫还有 Scrapy、py-spider 可选),大家都用它。
  • 老师自谦讲得浅,所以称"数据处理"而非"数据分析"——数据分析与挖掘是专门的课程。

Pandas 的数据观:Series 与 DataFrame(约 05:30 - 09:00)

  • 理解工具前先要理解它如何看待数据。Pandas 把表格看成两种数据类型:
  • Series(序列):对应表格中的一列(如 name 列、team 列、number 列),本质类似 Python 列表,但操作方式略有区别。
  • DataFrame:多个 Series 在索引(index)统一后拼接起来的表格,有行(row)、列(column),中间的数据叫单元格(cell)。
  • 这种结构与直觉高度一致,是 Pandas 受欢迎的原因之一。

环境安装与读取文件(约 09:00 - 14:30)

  • 安装:pipenv install pandas;Pandas 读 Excel 依赖第三方 Excel 库(openpyxl/xlrd),也要装。
  • 惯例导入别名:import pandas as pd;变量 df 是 DataFrame 首字母缩写。
  • 读 CSV:df = pd.read_csv('文件.csv');读 Excel:pd.read_excel('文件.xlsx')(老师课上忘了把 read_csv 改成 read_excel 导致 UTF-8 报错,现场排错)。
  • 打印 df 输出非常规整:表头、从 0 开始的行号;一个库即可读多种类型文件,读入后统一为 DataFrame。

Series 的创建(约 15:30 - 21:00)

  • 直接传列表:s = pd.Series([1,2,3,4,5]),默认索引(index)为 0,1,2,3,4(与 C 数组/Python 列表一样)。
  • 注意 dtype:Pandas 数据有数据类型和宽度的概念,默认整数为 int64(64 比特)。这与 Python 原生整数"无限精度、无宽度概念"不同,更接近 C 语言——科学计算必须考虑数据宽度,否则会有误差和表示不准的问题,Pandas 帮你处理好了。
  • 自定义索引:pd.Series([...], index=['A','B','C','D','E']),可把行号换成任意标签。把它想象成数据的 X 轴/Y 轴(如用户 ID → 相关信息)就有意义了。
  • 直接传字典:pd.Series({'a': 1, ...}),key 作索引、value 作值,效果与指定 index 等价。

NumPy 背景知识(约 21:00 - 24:00)

  • NumPy 是 Python 科学计算领域特别有名的库,用于处理矩阵(如 2×5 矩阵及加减乘除、特征值等线性代数运算)。
  • Pandas 基于 NumPy 开发;安装 pandas 时会自动装好 numpy,无需单独安装。
  • 矩阵概念与 DataFrame/表格高度相似,操作 DataFrame 时会结合 NumPy 一起看(本课不展开)。

DataFrame 的创建(约 24:00 - 37:20)

  • 方式一:随机矩阵 + 索引 + 列名
dates = pd.date_range('20130101', periods=6)   # 生成日期范围,返回 DatetimeIndex,dtype 为 datetime64,freq='D'
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
  • pd.date_range(起始日期字符串, periods=天数) 生成时间序列,可作行索引;Python 内置有 datetime 库处理日期,Pandas 的 date_range 更方便。
  • np.random.randn(6, 4) 生成 6 行 4 列的随机矩阵,数值服从标准(正态)分布。
  • columns=list('ABCD') 指定四列列名。
  • 方式二:传字典,每个 key 对应一列(不是一行):
df2 = pd.DataFrame({
    'A': 1.0,
    'B': pd.Timestamp('20130102'),
    'C': pd.Series(1, index=list(range(4)), dtype='float32'),
    'D': np.array([3] * 4, dtype='int32'),
    'E': pd.Categorical(['test', 'train', 'test', 'train']),
    'F': 'foo'
})
  • 要点回顾(约 36:00):① 数据会**自动补全/填充**——按最长列的行数把单值列(如 A 的 1.0、F 的 'foo')复制填满;② 若某些列没写 index,会自动采用其他列的索引;③ 每个 key 对应一列(一个 Series),凭直觉容易误以为是行,务必注意。

查看与选择数据(约 37:20 - 50:00)

  • df.head() 默认取前 5 行(可传参);df.tail(3) 取尾部 3 行。
  • df.T 转置:行列互换(与数学、Excel 选择性粘贴中的转置一致)。
  • 按标签选择 loc(方括号切片,不是函数调用):df.loc[dates[0]] 取某一行;df.loc[:, ['A', 'B']] 取所有行的 A、B 两列——逗号前指定行(: 表示全部),逗号后用列表指定列,可以跳选(如只选 A 和 D)。
  • 按位置选择 iloc(带 i):用行号列号,如 df.iloc[[1,2,4], [0,2]] 选出第 1、2、4 行与第 0、2 列交叉区域,拼成新表格。
  • 条件筛选(约 43:00,非常有用):
  • df[df.A > 0]:选出 A 列大于 0 的所有行。应用场景举例:一键筛出中测不及格(成绩列 < 60)的同学及科目、筛出爬取的电影中评分 8 分以上的。
  • df[df > 0]:对整个表格筛选,大于 0 的值保留,不满足的被填成 NaN。
  • NaN 是 NumPy 中 Not a Number 的缩写,表示无效/不合法数据,含义类似 Python 的 None。
  • df2[df2['E'].isin(['two', 'four'])]:isin 方法选出某列值在指定集合中的所有行。
  • 以上筛选**不改变原表**,只是把一部分拿出来看。

赋值与列操作(约 50:00 - 56:00)

  • df.copy() 复制出内容一致但独立的新表。
  • 新增列:df['F'] = pd.Series(...)。对齐规则:新 Series 按索引对齐到原表,原表缺失的位置填 NaN;新列中超出原表索引范围的数据会被**直接丢弃**(如原表到 1 月 6 号,新列 1 月 7 号的值被舍弃)。
  • 精确到单元格赋值:df.at[dates[0], 'A'] = 0(按标签,不能切片);df.iat[0, 1] = 0(按序号,与 loc/iloc 的对应关系一致)。
  • 条件赋值:df[df > 0] = -df——把原表中所有正数取反,负数不变;结合筛选可实现条件更明确的批量赋值。

异常(缺失)数据处理(约 56:00 - 58:43)

  • df.dropna():丢弃任何包含 NaN 的行。
  • df.fillna(value)(更常用):把所有 NaN 填成指定值(数字或字符串均可)。典型场景:爬虫数据清洗——爬不到的字段(如知乎性别为 -1)先置为 NaN,再统一填充为便于后续计算的值;NaN 无法参与乘法等运算,必须先填充。

示例与演示

  • 演示 1(读文件):虚拟环境中 pipenv install pandas + Excel 依赖库,pd.read_csv 读取上节课的人员信息 CSV 并打印;改后缀读 xlsx 时报 UTF-8 错,发现是忘了把 read_csv 改成 read_excel,改后正常。
  • 演示 2(Series):pd.Series([1,2,3,4,5]) 观察默认索引 0-4 与 dtype int64;再用 index=['A','B','C','D','E'] 自定义索引;再传字典得到同样效果。
  • 演示 3(DataFrame 创建):date_range('20130101', periods=6) 生成日期索引;np.random.randn(6,4) 生成随机矩阵;组合成 6 行 4 列 DataFrame。又用字典方式创建 df2(含 Timestamp、Categorical 等列),展示自动补全。
  • 演示 4(选择数据):head/tail/T 概览;loc 按日期标签取行、:, ['A','B'] 取列;iloc 按序号跳选;重点演示 df[df.A > 0](配合打印原始矩阵对比,某行 A 列为负被整行过滤)和 df[df > 0](负值变 NaN)。
  • 演示 5(赋值):新增索引错位的 F 列,展示 NaN 填充与超范围丢弃;at/iat 单元格置 0;df[df>0] = -df 正数取反。
  • 异常处理(dropna/fillna)因时间关系未现场运行,布置学生参照课件自己跑。

重点与难点

  • dtype 概念:Pandas 数据有类型宽度(int64、float32、datetime64),不同于 Python 原生无限精度整数。
  • 字典创建 DataFrame 时 key 对应列而不是行;短列会自动按最长行数填充。
  • loc(按标签)/iloc(按序号)是**方括号切片机制,不是函数调用**;at/iat 只能精确定位单个单元格。
  • 条件筛选 df[df.A > 0] 是极常用的操作(筛不及格成绩、筛高分电影);整表筛选不满足项变 NaN。
  • 新增列时索引对齐规则:缺失填 NaN、超范围丢弃,容易踩坑。
  • NaN 无法参与数值运算,后续处理前用 dropna 或 fillna 清理。
  • 老师反复强调的工作方式:左屏代码右屏文档/谷歌,一边查一边写。

关联内容

  • 承接 15.1:csv/openpyxl 是轻量方案,Pandas 是"一网打尽"各种数据源的重型方案;Pandas 读 Excel 底层正依赖 openpyxl/xlrd。
  • 与爬虫章节联动:示例多次提到"爬下来的数据"(知乎回答、电影评分)可用本课方法筛选清洗。
  • 为 15.3 Matplotlib 可视化和 15.4 综合实例(分类汇总、排序、画图)打基础。
  • 前置知识:Python 列表/字典/切片、线性代数矩阵概念、datetime、pipenv 虚拟环境。
  • 提及 Pandas 基于 NumPy,NumPy 本身本课不展开,属后续可自学内容。