Pandas第二章 基础
一.文件的读取和写入
1.文件读取
(1)基础读取方法
pandas 支持读取csv、excel、txt三类常见文件,对应核心函数如下:
| 文件类型 | 读取函数 | 示例代码 |
|---|---|---|
| CSV | pd.read_csv() | |
| Excel | pd.read_excel() | |
| TXT | pd.read_table() | |
(2)常用公共参数(三类函数通用)
这些参数可以在read_csv/read_excel/read_table中混用,用于精细化控制读取行为:
| 参数名 | 作用 | 示例 |
|---|---|---|
header=None | 不将文件第一行作为列名,自动生成数字列名 | |
index_col | 指定一列或多列作为 DataFrame 索引 | |
usecols | 仅读取指定列集合,减少内存占用 | |
parse_dates | 将指定列解析为 datetime 时间类型 | |
nrows | 仅读取前 N 行数据,适合预览大文件 | |
(3)TXT 文件特殊分隔符处理
read_table默认以空白字符为分隔符,若 TXT 使用自定义分隔符(如||||),需通过sep参数指定:
- 注意:
sep是正则表达式参数,特殊字符(如|)需要转义为\\| - 必须指定引擎:使用多字符分隔符时,需添加
engine='python'避免报错
# 读取以 |||| 分隔的 TXT 文件 pd.read_table( '../data/my_table_special_sep.txt', sep='\\|\\|\\|\\|', engine='python' )注:
- 读取大文件时,优先用
usecols和nrows减少数据加载量- 时间列务必用
parse_dates提前解析,避免后续类型转换麻烦- 自定义分隔符的 TXT 文件,记得对
|等特殊字符做正则转义,并指定engine='python'
2.基础文件写入
(1)基础写入方法
pandas 中 DataFrame 写入文件的核心操作,强烈建议设置index=False,避免无意义的索引列被写入文件:
| 目标文件类型 | 写入函数 | 示例代码 |
|---|---|---|
| CSV | df.to_csv() | |
| Excel | df.to_excel() | |
| TXT | 用df.to_csv()实现 | |
注意:pandas 没有
to_table()函数,TXT 文件需通过to_csv()+ 自定义分隔符实现,常用制表符\t作为分隔。
(2)格式转换输出(Markdown / LaTeX)
如果需要将表格快速转换为文档格式,可使用以下函数(需先安装tabulate包):
| 目标格式 | 转换函数 | 示例代码 |
|---|---|---|
| Markdown | df.to_markdown() | |
| LaTeX | df.to_latex() | |
输出效果示例:
Markdown 格式:
| | col1 | col2 | col3 | col4 | col5 | |----|--------|--------|--------|---------|-----------| | 0 | 2 | a | 1.4 | apple | 2020/1/1 | | 1 | 3 | b | 3.4 | banana | 2020/1/2 | | 2 | 6 | c | 2.5 | orange | 2020/1/5 | | 3 | 5 | d | 3.2 | lemon | 2020/1/7 |LaTeX 格式:
\begin{tabular}{lr lr ll} \toprule {} & col1 & col2 & col3 & col4 & col5 \\ \midrule 0 & 2 & a & 1.4 & apple & 2020/1/1 \\ 1 & 3 & b & 3.4 & banana & 2020/1/2 \\ 2 & 6 & c & 2.5 & orange & 2020/1/5 \\ 3 & 5 & d & 3.2 & lemon & 2020/1/7 \\ \bottomrule \end{tabular}
注:
- 索引控制:
index=False是写入文件的最佳实践,可避免生成冗余索引列。- TXT 分隔符:写入 TXT 时,
sep参数可自定义(如sep=','或sep='|'),需与读取时的分隔符保持一致。
二.基本数据结构
1.Series(一维数据结构)
(1)基本概念
Series 是 pandas 中存储一维数据的核心结构,由 4 个部分组成:
data:序列的值index:索引(可自定义名称,默认为空)dtype:数据存储类型name:序列本身的名字
import pandas as pd s = pd.Series( data = [100, 'a', {'dic1':5}], index = pd.Index(['id1', 20, 'third'], name='my_idx'), dtype = 'object', name = 'my_name' )(2)核心属性获取
| 属性 | 作用 | 示例代码 |
|---|---|---|
s.values | 获取序列值数组 | |
s.index | 获取索引对象 | |
s.dtype | 获取数据类型 | |
s.name | 获取序列名称 | 'my_name' |
s.shape | 获取序列长度 | (n,) |
object 类型说明:代表混合类型,可存储整数、字符串、字典等不同 Python 对象;纯字符串序列也默认是 object 类型,也可使用
string类型存储。
2.DataFrame(二维数据结构)
DataFrame 是在 Series 基础上增加了列索引,用于存储二维表格数据,由二维数据 + 行索引 + 列索引构成。
(1) 两种常见创建方式
- 方式 1:二维列表 + 行列索引
data = [[1, 'a', 1.2], [2, 'b', 2.2], [3, 'c', 3.2]] df = pd.DataFrame( data = data, index = ['row_%d'%i for i in range(3)], columns=['col_0', 'col_1', 'col_2'] )- 方式 2:字典映射(更常用)
df = pd.DataFrame( data = { 'col_0': [1,2,3], 'col_1': list('abc'), 'col_2': [1.2, 2.2, 3.2] }, index = ['row_%d'%i for i in range(3)] )(2)列选取
| 选取方式 | 语法 | 返回结果 |
|---|---|---|
| 选取单列 | df['col_0'] | Series |
| 选取多列 | df[['col_0', 'col_1']] | DataFrame |
(3)核心属性获取
| 属性 | 作用 | 示例代码 |
|---|---|---|
df.values | 获取二维数据数组 | |
df.index | 获取行索引 | |
df.columns | 获取列索引 | |
df.dtypes | 获取各列数据类型(返回 Series) | |
df.shape | 获取行列数 | (3, 3) |
df.T | 转置 DataFrame(行变列、列变行) | 行列互换后的新 DataFrame |
联系:DataFrame 的每一列本质上都是一个 Series,列与列之间可以是不同数据类型。
三.常用基本函数
1.汇总函数head()/tail()
| 函数 | 作用 | 示例 | 默认值 |
|---|---|---|---|
df.head(n) | 返回前n行 | df.head(2)→ 返回前 2 行 | n=5 |
df.tail(n) | 返回后n行 | df.tail(3)→ 返回后 3 行 | n=5 |
用途:快速查看数据格式、字段和样本,避免加载全量数据。
2.信息概览函数info()
df.info()用于查看数据集基础结构信息:
- 数据类型:
<class 'pandas.core.frame.DataFrame'> - 行数:
RangeIndex: 200 entries, 0 to 199(共 200 行) - 列信息:列名、非空值数量、数据类型
- 内存占用:
memory usage: 11.1+ KB
3.统计描述函数describe()
df.describe()仅对数值型列生成统计量:
| 统计量 | 含义 |
|---|---|
count | 非空样本数 |
mean | 均值 |
std | 标准差 |
min | 最小值 |
25%/50%/75% | 下四分位数 / 中位数 / 上四分位数 |
max | 最大值 |
注:
head()/tail()适合快速预览,info()适合检查缺失值和数据类型,describe()适合快速了解数值分布。- 若需对文本 / 分类列做统计,可使用
df.describe(include='object')。- 大数据集场景下,
info()和describe()是轻量高效的探索工具。
四.特征统计函数
1.基础统计函数
针对数值型列,pandas 提供了常用的聚合统计函数,操作后返回标量或 Series:
| 函数 | 含义 | 示例代码 | 示例结果 |
|---|---|---|---|
sum() | 求和 | df_demo.sum() | Height: 29869.0, Weight: 10397.0 |
mean() | 均值 | df_demo.mean() | Height: 163.218033, Weight: 55.015873 |
median() | 中位数 | df_demo.median() | Height: 161.9, Weight: 51.0 |
var() | 方差 | df_demo.var() | Height: 74.046, Weight: 164.446 |
std() | 标准差 | df_demo.std() | Height: 8.608879, Weight: 12.824294 |
max() | 最大值 | df_demo.max() | Height: 193.9, Weight: 89.0 |
min() | 最小值 | df_demo.min() | Height: 145.4, Weight: 34.0 |
2.进阶统计函数
| 函数 | 含义 | 示例代码 | 示例结果 |
|---|---|---|---|
quantile(q) | 分位数(q 为 0~1 之间的数) | df_demo.quantile(0.75) | Height: 167.5, Weight: 65.0 |
count() | 非缺失值个数 | df_demo.count() | Height: 183, Weight: 189 |
idxmax() | 最大值对应的索引 | df_demo.idxmax() | Height: 193, Weight: 2 |
idxmin() | 最小值对应的索引 | df_demo.idxmin() | - |
3.聚合方向参数axis
所有聚合函数都有axis参数,用于控制聚合方向:
axis=0(默认):逐列聚合,对每一列计算统计量axis=1:逐行聚合,对每一行计算统计量
# 逐行求均值(示例:身高+体重的均值,无实际业务意义,仅演示语法) df_demo.mean(axis=1).head()输出:
0 102.45 1 118.25 2 138.95 3 41.00 4 124.00 dtype: float64注:
- 聚合函数定义:操作后返回标量(或按列 / 行聚合的 Series),因此也叫聚合函数。
- 缺失值处理:
count()会自动忽略缺失值,统计非空样本数量;mean()/sum()等也默认忽略缺失值计算。- 业务场景提示:逐行聚合(
axis=1)需结合业务逻辑使用,比如本数据集中 “身高 + 体重的均值” 无实际意义,仅用于语法演示。- 快速查看多列统计量:
df[['Height','Weight']].describe()- 同时计算多个统计量:
df_demo.agg(['mean','max','count'])- 对不同列应用不同统计量:
df_demo.agg({'Height':'mean','Weight':'max'})
五.唯一值操作
1.单列组合
针对单个 Series(列),常用函数如下:
| 函数 | 作用 | 示例代码 | 示例结果 |
|---|---|---|---|
unique() | 返回所有唯一值组成的数组 | df['School'].unique() | ['Shanghai Jiao Tong University', 'Peking University', 'Fudan University', 'Tsinghua University'] |
nunique() | 返回唯一值的个数 | df['School'].nunique() | 4 |
value_counts() | 返回唯一值及其出现频次 | df['School'].value_counts() | Tsinghua University: 69, Shanghai Jiao Tong University: 57, ... |
drop_duplicates() | 去重,保留唯一值 | df['School'].drop_duplicates() | 保留 4 个不同学校名称 |
duplicated() | 返回布尔序列,标记重复行 | df['School'].duplicated().head() | [False, False, True, False, True] |
2.多列组合
(1)drop_duplicates()
- 作用:按指定列组合去重,保留符合条件的行
- 关键参数
keep:first(默认):保留每个组合第一次出现的行last:保留每个组合最后一次出现的行False:剔除所有重复组合,只保留出现一次的组合
- 示例:
# 按 Gender + Transfer 组合去重,保留第一次出现 df_demo.drop_duplicates(['Gender', 'Transfer']) # 按 Gender + Transfer 组合去重,保留最后一次出现 df_demo.drop_duplicates(['Gender', 'Transfer'], keep='last') # 只保留 Name + Gender 组合出现一次的行 df_demo.drop_duplicates(['Name', 'Gender'], keep=False)
(2)duplicated()
- 作用:返回布尔序列,标记重复行(重复为
True,首次出现为False) - 与
drop_duplicates()的关系:drop_duplicates()等价于删除duplicated()为True的行 - 示例:
df_demo.duplicated(['Gender', 'Transfer']).head() # 输出:0 False, 1 False, 2 True, 3 True, 4 True
(3)核心区别与联系
| 函数 | 输入 | 输出 | 典型用途 |
|---|---|---|---|
unique() | Series | 数组 | 查看类别取值 |
nunique() | Series | 标量 | 统计类别数量 |
value_counts() | Series | Series | 统计类别分布 |
drop_duplicates() | Series/DataFrame | Series/DataFrame | 去重、保留唯一组合 |
duplicated() | Series/DataFrame | 布尔 Series | 标记重复行、筛选重复数据 |
注:
value_counts()默认按频次降序排列,可加sort=False保持原顺序drop_duplicates()可作用于整个 DataFrame,默认按所有列组合去重duplicated()可配合~取反,筛选不重复行:df[~df.duplicated()]
六.替换函数
1.映射替换:replace
replace是最基础的映射替换方法,支持字典或列表两种映射方式:
| 写法 | 示例代码 | 说明 |
|---|---|---|
| 字典映射 | | 键为原值,值为替换后的值 |
| 列表映射 | | 两个列表一一对应,按顺序替换 |
方向替换(method 参数):
method='ffill':用前面最近的未被替换值填充method='bfill':用后面最近的未被替换值填充
s = pd.Series(['a', 1, 'b', 2, 1, 1, 'a']) s.replace([1, 2], method='ffill') # 用前面的 a/b 替换 1/2 s.replace([1, 2], method='bfill') # 用后面的 a/b 替换 1/2注:正则替换建议使用str.replace,当前版本replace对 string 类型正则替换存在 bug。
2.逻辑替换:where&mask
where和mask是完全对称的逻辑替换函数:
where(condition):条件为 False 的行被替换(默认替换为 NaN)mask(condition):条件为 True 的行被替换(默认替换为 NaN)
| 函数 | 示例代码 | 结果说明 |
|---|---|---|
where | s.where(s<0) | 保留负数,非负数变为 NaN |
where | s.where(s<0, 100) | 保留负数,非负数替换为 100 |
mask | s.mask(s<0) | 负数变为 NaN,非负数保留 |
mask | s.mask(s<0, -50) | 负数替换为 -50,非负数保留 |
条件可以是自定义布尔序列,只要索引与原 Series 一致即可:
s_condition = pd.Series([True,False,False,True], index=s.index) s.mask(s_condition, -50) # 按自定义布尔序列替换3.数值替换:round/abs/clip
针对数值型数据的专用替换函数:
| 函数 | 作用 | 示例代码 | 结果 |
|---|---|---|---|
round(n) | 四舍五入到 n 位小数 | s.round(2) | 1.2345 → 1.23 |
abs() | 取绝对值 | s.abs() | -1 → 1,-50 → 50 |
clip(lower, upper) | 截断到 [lower, upper] 区间 | s.clip(0, 2) | -1 → 0,100 → 2 |
4.三类替换函数对比
| 类别 | 核心函数 | 典型场景 |
|---|---|---|
| 映射替换 | replace | 类别型变量编码(如性别→0/1)、批量值映射 |
| 逻辑替换 | where/mask | 按条件筛选并替换(如异常值修正) |
| 数值替换 | round/abs/clip | 数值精度处理、范围截断、符号转换 |
七.排序函数
1.值排序:sort_values
按数据列的值进行排序,支持单列 / 多列排序、升序 / 降序控制。
(1)基础用法(单列排序)
# 按身高升序排序(默认 ascending=True) df_demo.sort_values('Height').head() # 按身高降序排序 df_demo.sort_values('Height', ascending=False).head()ascending=True(默认):升序(从小到大)ascending=False:降序(从大到小)
(2)多列排序
按多列组合排序,需为每一列指定排序方向:
# 体重升序,体重相同时身高降序 df_demo.sort_values( by=['Weight', 'Height'], ascending=[True, False] ).head()by:排序列名列表,按列表顺序依次排序ascending:布尔列表,与by一一对应,分别控制每一列的排序方向
2.索引排序:sort_index
按索引(行 / 列索引)进行排序,支持多级索引,用法与sort_values完全一致。
(1)基础用法(多级索引排序)
# 按 Grade 升序、Name 降序排序多级索引 df_demo.sort_index( level=['Grade', 'Name'], ascending=[True, False] ).head()level:指定索引层(可传索引名或层号)ascending:布尔列表,与level一一对应,控制每一层索引的排序方向- 字符串索引按字母顺序排序
3.对比
| 函数 | 排序对象 | 核心参数 | 典型场景 |
|---|---|---|---|
sort_values | 数据列 | by(列名)、ascending | 按数值 / 类别列排序(如身高、体重排序) |
sort_index | 索引 | level(索引层)、ascending | 按行 / 列索引排序(如多级索引分类排序) |
注:
- 多级索引:
sort_index可通过level指定索引层,实现多级索引的灵活排序- 排序稳定性:pandas 排序默认稳定,相同值的行保持原相对顺序
- 缺失值处理:
sort_values默认将 NaN 放在排序结果末尾(可通过na_position调整)
- 快速查看排序结果:配合
.head()预览前几行- 多列排序时,
ascending列表长度必须与by列表长度一致- 索引排序对字符串列按字母顺序,如需自定义顺序可使用
Categorical
八.apply方法
apply是 pandas 中用于行 / 列迭代的灵活方法,支持传入自定义函数,实现对 DataFrame 的列迭代或行迭代。
1.核心原理
axis参数控制迭代方向,与聚合函数完全一致:axis=0(默认):列迭代,每次传入一列(Series)axis=1:行迭代,每次传入一行(Series)
- 传入的函数以 ** 序列(Series)** 为输入,返回标量或序列,最终聚合为结果。
2.示例
(1)自定义函数实现均值计算
df_demo = df[['Height', 'Weight']] # 方式1:定义普通函数 def my_mean(x): return x.mean() df_demo.apply(my_mean) # 方式2:lambda 表达式简化 df_demo.apply(lambda x: x.mean()) #Height 163.218033 Weight 55.015873 dtype: float64(2)行迭代(逐行计算均值)
df_demo.apply(lambda x: x.mean(), axis=1).head() ### 0 102.45 1 118.25 2 138.95 3 41.00 4 124.00 dtype: float64 ###3.自定义统计量mad
mad(平均绝对偏差)的计算公式:
序列中每个元素与均值的绝对偏差的平均值
# 用 apply 实现 mad df_demo.apply(lambda x: (x - x.mean()).abs().mean()) # 等价于 pandas 内置 mad 函数 df_demo.mad() # Height 6.707229 Weight 10.391870 dtype: float64 #注:
- 性能警告:
apply自由度高,但性能远低于 pandas 内置函数。仅在无内置函数可替代的自定义场景下使用。- 迭代对象:
axis=0传入列,axis=1传入行,需根据需求选择。- lambda 简化:简单逻辑优先用 lambda 表达式,复杂逻辑用普通函数。
九.窗口对象
1.滑动窗口rolling
(1)基础用法
- 核心作用:对序列按固定窗口大小做滑动计算
- 核心参数:
window(窗口大小),axis(默认 0,列方向)
s = pd.Series([1,2,3,4,5]) roller = s.rolling(window=3) # 创建窗口大小为3的滑窗对象(2) 常用聚合计算
滑窗对象支持所有聚合函数,窗口包含当前行元素:
| 函数 | 作用 | 示例结果(window=3) |
|---|---|---|
mean() | 滑动均值 | [NaN, NaN, 2.0, 3.0, 4.0] |
sum() | 滑动求和 | [NaN, NaN, 6.0, 9.0, 12.0] |
cov(s2) | 滑动协方差 | 两序列窗口内协方差 |
corr(s2) | 滑动相关系数 | 两序列窗口内相关系数 |
(3)自定义函数apply
支持传入自定义函数,输入为窗口内的 Series:
# 等价于 roller.mean() roller.apply(lambda x: x.mean())2.类滑窗函数shift/diff/pct_change
这类函数公共参数为periods=n(默认 1),支持正负 n(反方向操作):
| 函数 | 作用 | 示例(s = [1,3,6,10,15]) |
|---|---|---|
shift(n) | 取向前第 n 个元素的值 | shift(2)→[NaN, NaN, 1, 3, 6] |
diff(n) | 与向前第 n 个元素做差(n 阶差分) | diff(3)→[NaN, NaN, NaN, 9, 12] |
pct_change(n) | 与向前第 n 个元素相比计算增长率 | pct_change()→[NaN, 2.0, 1.0, 0.666..., 0.5] |
(1)反方向操作(n 为负)
shift(-1):取向后第 1 个元素 →[3,6,10,15,NaN]diff(-2):与向后第 2 个元素做差 →[-5, -7, -9, NaN, NaN]
(2)等价滑窗实现
类滑窗函数可通过rolling等价实现:
# shift(2) 等价于 rolling(3) 取窗口第一个元素 s.rolling(3).apply(lambda x: list(x)[0]) # diff(3) 等价于 rolling(4) 取首尾元素差 s.rolling(4).apply(lambda x: list(x)[-1]-list(x)[0]) # pct_change() 等价于 rolling(2) 计算增长率 def my_pct(x): L = list(x) return L[-1]/L[0]-1 s.rolling(2).apply(my_pct)3. 扩张窗口(累计窗口)expanding
(1)核心原理
扩张窗口(又称累计窗口)是动态长度的窗口:
- 窗口范围:从序列起始位置到当前位置,窗口长度随位置逐步扩张
- 示例:序列
[a1, a2, a3, a4]对应窗口为[a1]、[a1,a2]、[a1,a2,a3]、[a1,a2,a3,a4] - 本质:对序列做累计聚合计算,等价于
rolling(window=当前位置+1)的特殊滑动窗口
(2)用法示例
s = pd.Series([1, 3, 6, 10]) # 创建扩张窗口对象,计算累计均值 s.expanding().mean()计算过程拆解:
| 位置 | 窗口范围 | 计算 | 结果 |
|---|---|---|---|
| 0 | [1] | 1/1 | 1.0 |
| 1 | [1,3] | (1+3)/2 | 2.0 |
| 2 | [1,3,6] | (1+3+6)/3 | 3.333333 |
| 3 | [1,3,6,10] | (1+3+6+10)/4 | 5.0 |
(3)常用聚合函数
扩张窗口支持所有 pandas 聚合函数,与rolling完全一致:
- 基础统计:
mean()、sum()、median()、max()、min() - 离散统计:
count()、quantile() - 自定义函数:
apply(lambda x: ...)
注:
- 窗口计算规则:滑动窗口包含当前行元素,如第 4 个位置计算均值为
(2+3+4)/3,而非(1+2+3)/3- 缺失值处理:窗口不足时默认返回 NaN
- 性能提示:优先使用内置聚合函数,
apply仅用于自定义场景- 后续内容:日期偏置窗口、指数加权窗口将在后续章节讲解
- 扩张窗口可理解为窗口大小无限扩张的滑动窗口,
expanding()等价于rolling(window=len(s), min_periods=1)- 支持
axis参数,可对 DataFrame 做列 / 行方向的累计聚合
