【Python系列课程】21 Pandas(四):文件读写与实战案例
> 前几篇我们把Pandas的数据结构、清洗、分组、合并都讲透了。本篇来到工程落地的关键环节——怎么把数据读进来,怎么把结果写出去。真实工作中,数据80%来自CSV或Excel文件,学会这两件事你就能解决实际问题了。
一、CSV文件读写(最常用!)
CSV(Comma Separated Values)是数据分析中最常见的文件格式,用逗号分隔各列。Pandas对CSV的支持是最完善的。
1.1 读取CSV:read_csv()
先准备一个测试用的CSV文件:
`python
import pandas as pd
先创建一个测试DataFrame并写入CSV,方便演示读取
df = pd.DataFrame({
'名字': ['张三', '李四', '王五', '赵六', '孙七'],
'年龄': [18, 19, 20, 22, 17],
'身高': [188, 178, 189, 175, 177]
})
df.to_csv('test01.csv', index=False)
print("test01.csv 已创建")
`基础读取:
`python
df = pd.read_csv('test01.csv')
print(df)
名字 年龄 身高
0 张三 18 188
1 李四 19 178
2 王五 20 189
3 赵六 22 175
4 孙七 17 177
`> [图1:CSV文件在VS Code中的原始内容截图——用逗号分隔,第一行为列名]
#### 关键参数详解
| 参数 | 默认值 | 说明 |
|
|
--|
|
| sep | ',' | 分隔符,如';'、'\t'(制表符) |
| header | 0 | 哪一行作为列名,None表示没有列名 |
| names | None | 自定义列名列表,会覆盖header |
| index_col | None | 哪一列作为行索引 |
| usecols | None | 只读取指定的列(节省内存!) |
| nrows | None | 只读取前N行(大文件预览用) |
| skiprows | None | 跳过指定行(整数或列表) |
| encoding | None(自动推断) | 文件编码,中文常用'utf-8'或'gbk' |
| chunksize | None | 分块读取,返回迭代器(超大文件用) |
sep:非逗号分隔的文件
`python
假设test02.csv用分号分隔
df = pd.read_csv('test02.csv', sep=';')
`header:控制哪行作为列名
`python
header=None:不将任何行作为列名,自动生成0,1,2...
df = pd.read_csv('test03.csv', sep=';', header=None)
print(df)
0 1 2
0 张三 18 188
1 李四 19 178
header=2:第3行作为列名(前面2行跳过)
df = pd.read_csv('test03.csv', sep=';', header=2)
`names:自定义列名
`python
用names指定列名,配合header=None使用
df = pd.read_csv('test02.csv', sep=';',
names=['name', 'age', 'height'])
print(df)
`nrows + skiprows:大文件高效读取
`python
只读取前2行(预览数据)
df = pd.read_csv('test01.csv', nrows=2)
print(df)
跳过前2行(跳过表头,直接读数据)
df = pd.read_csv('test01.csv', skiprows=2)
print(df)
跳过指定行(第0行和第2行)
df = pd.read_csv('test01.csv', skiprows=[0, 2])
print(df)
`usecols:只读需要的列(超大文件必备!)
`python
只读取第0列和第2列
df = pd.read_csv('test01.csv', usecols=[0, 2])
print(df)
`chunksize:分块读取超大文件
`python
chunksize=2:每次迭代返回2行
chunk_iter = pd.read_csv('test01.csv', chunksize=2)
print(type(chunk_iter)) #
for chunk in chunk_iter:
print("
一个chunk
")
print(chunk)`
> [图2:read_csv各参数效果对比示意图——用并排的DataFrame展示不同参数的输出差异]
1.2 写入CSV:to_csv()
`python
df = pd.DataFrame({
'名字': ['张三', '李四', '王五'],
'年龄': [18, 19, 20],
'身高': [188, 178, 189]
})
基础写入:逗号分隔,包含行索引和列名
df.to_csv('./test04.csv')
不写入行索引
df.to_csv('./test05.csv', index=False)
不写入列名
df.to_csv('./test06.csv', header=False)
用分号作为分隔符
df.to_csv('./test07.csv', sep=';', index=False)
`> ⚠️ 中文编码问题:如果CSV用Excel打开乱码,写入时指定 encoding='utf-8-sig'(Excel能正确识别的UTF-8 BOM格式)。
二、Excel文件读写
Excel文件(.xlsx)比CSV功能更强——支持多个工作表、单元格格式、公式等。Pandas通过 openpyxl 引擎支持Excel读写(需要先 pip install openpyxl)。
2.1 写入Excel:to_excel()
`python
df = pd.DataFrame({
'名字': ['张三', '李四', '王五', '赵六', '孙七'],
'年龄': [18, 19, 20, 22, 17],
'身高': [188, 178, 189, 175, 177]
})
基础写入:默认写入第一个工作表(Sheet1)
df.to_excel('./test08.xlsx')
不写入行索引
df.to_excel('./test09.xlsx', index=False)
不写入列名
df.to_excel('./test10.xlsx', header=False)
`写入多个工作表(这是Excel的杀手锏功能):
`python
方式1:用ExcelWriter + close()
writer = pd.ExcelWriter('./test11.xlsx')
df.to_excel(writer, sheet_name='工作表1', index=False)
df.iloc[:, :2].to_excel(writer, sheet_name='工作表2', index=False)
writer.close()
方式2:用with语句(推荐!自动关闭)
with pd.ExcelWriter('./test11.xlsx') as writer:
df.to_excel(writer, sheet_name='工作表1', index=False)
df.iloc[:, :2].to_excel(writer, sheet_name='工作表2', index=False)
`> [图3:Excel文件中包含两个工作表的截图——在Excel中打开test11.xlsx,可以看到底部有两个Sheet标签]
2.2 读取Excel:read_excel()
`python
基础读取:默认读取第一个工作表
df = pd.read_excel('./test11.xlsx')
print(df)
header=None:不将第一行作为列名
df = pd.read_excel('./test11.xlsx', header=None)
print(df)
header=2:第3行作为列名
df = pd.read_excel('./test11.xlsx', header=2)
print(df)
names:自定义列名(会覆盖header行)
df = pd.read_excel('./test11.xlsx',
names=['name', 'age', 'height'])
print(df)
sheet_name:指定读取哪个工作表
df = pd.read_excel('./test11.xlsx', sheet_name=1) # 整数:按索引
df = pd.read_excel('./test11.xlsx', sheet_name='工作表2') # 字符串:按名称
print(df)
读取多个工作表 → 返回字典
dfs = pd.read_excel('./test11.xlsx', sheet_name=[0, '工作表2'])
print(type(dfs)) #
print(dfs[0]) # 第一个工作表
print(dfs['工作表2']) # 名为"工作表2"的工作表
`大文件参数(和read_csv类似):
`python
只读前2行
df = pd.read_excel('./test11.xlsx', nrows=2)
跳过前2行
df = pd.read_excel('./test11.xlsx', skiprows=2)
跳过指定行
df = pd.read_excel('./test11.xlsx', skiprows=[0, 2])
只读指定列
df = pd.read_excel('./test11.xlsx', usecols=[0, 2])
`> [图4:read_excel读取指定工作表的输出截图——分别展示按索引和按名称读取的结果]
三、读取Excel时的常见坑点
坑点1:没有安装openpyxl
`python
第一次读取Excel时可能会报错:
ImportError: Missing optional dependency 'openpyxl'...
解决:pip install openpyxl
`坑点2:行索引被当作了数据
`python
如果写入Excel时用了 index=True(默认),读取时第一行会出现"Unnamed: 0"列
df.to_excel('test.xlsx') # index=True 默认
df = pd.read_excel('test.xlsx')
print(df.columns) # Index(['Unnamed: 0', '名字', '年龄', '身高'], ...)
解决:写入时加 index=False
df.to_excel('test.xlsx', index=False)
`坑点3:日期列被读成浮点数
Excel里的日期本质是序列号(如44927 = 2023-01-01),读取时需要指定:
`python
df = pd.read_excel('test.xlsx', parse_dates=['日期列名'])`
四、综合实战案例:分析销售数据
把本篇所学的所有内容串起来,做一个完整的"读取→清洗→分析→写出"流程。
场景:有一个销售数据.csv文件,包含日期、销售员、产品、销售额四列,需要:
1. 读取CSV文件
2. 清洗数据(处理缺失值、去重)
3. 按销售员统计总销售额和平均销售额
4. 找出销售额前3的产品
5. 将结果写入新的Excel文件(两个工作表:销售员统计 + 产品统计)
`python
import pandas as pd
import numpy as np
========== 步骤0:创建模拟数据(实际工作中这步是别人给你的CSV)==========
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=10).tolist() * 3
data = {
'日期': dates[:30],
'销售员': np.random.choice(['张三', '李四', '王五'], 30),
'产品': np.random.choice(['A产品', 'B产品', 'C产品'], 30),
'销售额': np.random.randint(100, 1000, 30).astype(float)
}
人为加入一些缺失值和重复行
data['销售额'][5] = np.nan
data['销售额'][12] = np.nan
df_raw = pd.DataFrame(data)
df_raw = pd.concat([df_raw, df_raw.iloc[[0, 3, 5]]]) # 加入重复行
df_raw.to_csv('销售数据.csv', index=False, encoding='utf-8-sig')
print("模拟数据已写入 销售数据.csv")
========== 步骤1:读取CSV ==========
df = pd.read_csv('销售数据.csv')
print(f"读取完成,数据形状: {df.shape}")
print("\n前5行:")
print(df.head())
========== 步骤2:数据清洗 ==========
print("\n=== 清洗前:各列缺失值统计 ===")
print(df.isnull().sum())
删除完全重复的行
df = df.drop_duplicates()
print(f"\n删除重复行后形状: {df.shape}")
填充销售额的NaN为平均值
salary_mean = df['销售额'].mean()
df['销售额'] = df['销售额'].fillna(salary_mean)
print(f"\n销售额NaN已填充为平均值: {salary_mean:.1f}")
print("\n=== 清洗后:各列缺失值统计 ===")
print(df.isnull().sum())
========== 步骤3:按销售员统计 ==========
sales_by_person = df.groupby('销售员')['销售额'].agg(
总销售额='sum',
平均销售额='mean',
订单数量='count'
).reset_index().sort_values('总销售额', ascending=False)
print("\n=== 各销售员统计 ===")
print(sales_by_person)
========== 步骤4:按产品统计,找出销售额前3 ==========
sales_by_product = df.groupby('产品')['销售额'].sum()\
.reset_index()\
.sort_values('销售额', ascending=False)
top3_products = sales_by_product.head(3)
print("\n=== 各产品总销售额(前3)===")
print(top3_products)
========== 步骤5:写入Excel(两个工作表)==========
with pd.ExcelWriter('销售分析结果.xlsx') as writer:
sales_by_person.to_excel(writer, sheet_name='销售员统计', index=False)
sales_by_product.to_excel(writer, sheet_name='产品统计', index=False)
print("\n分析结果已写入 销售分析结果.xlsx(含2个工作表)")
`> [图5:综合案例完整输出截图——包含读取预览、清洗统计、分组结果、Excel文件内容]
输出结果示例:
`
读取完成,数据形状: (33, 4)
=== 清洗前:各列缺失值统计 ===
日期 0
销售员 0
产品 0
销售额 2
删除重复行后形状: (30, 4)
销售额NaN已填充为平均值: 533.2
=== 清洗后:各列缺失值统计 ===
日期 0
销售员 0
产品 0
销售额 0
=== 各销售员统计 ===
销售员 总销售额 平均销售额 订单数量
0 张三 4825.6 536.18 9
1 李四 4218.3 527.29 8
2 王五 4562.1 507.98 9
分析结果已写入 销售分析结果.xlsx(含2个工作表)`
五、本文总结
| 操作 | 函数 | 关键参数 |
|
|
|
|
| 读取CSV | pd.read_csv() | sep, header, names, usecols, nrows, chunksize |
| 写入CSV | df.to_csv() | index=False, sep, encoding='utf-8-sig' |
| 读取Excel | pd.read_excel() | sheet_name, header, names, nrows |
| 写入Excel | df.to_excel() | index=False, sheet_name, 用ExcelWriter写多表 |
| 大文件读取 | read_csv(chunksize=...) | 返回迭代器,逐块处理 |
CSV vs Excel 怎么选?
| 场景 | 推荐格式 | 理由 |
|
|
|
|
| 数据量大(>10万行) | CSV | 文件小,读写快 |
| 需要多个工作表 | Excel | CSV不支持多表 |
| 需要保留单元格格式 | Excel | CSV纯文本,无格式 |
| 跨平台数据交换 | CSV | 任何系统都能打开 |
| 中文数据给非技术人员 | Excel | 对方更熟悉 |
六、Pandas四篇总结
到这里,Pandas四部曲全部结束。回顾一下我们学了什么:
| 篇目 | 核心内容 | 你应该能做的事 |
|
--|
|
--|
| 第18篇 | Series、DataFrame的创建和访问 | 创建任意结构的表格,用loc/iloc精准访问数据 |
| 第19篇 | 缺失值处理、去重、排序、类型转换 | 清洗真实世界的脏数据 |
| 第20篇 | groupby分组聚合、concat/merge合并 | 做SQL能做的所有分析操作 |
| 第21篇(本篇) | CSV/Excel读写、综合实战 | 端到端完成一个数据分析项目 |
下一篇开始进入Matplotlib——让数据"看得见"。
动手练习
1. 创建一个包含5行3列的DataFrame(列名自拟),将其写入CSV文件(不要行索引),然后再读取回来,验证数据一致。
2. 创建一个DataFrame,将其同时写入Excel的两个工作表中(比如"原始数据"和"汇总数据"),然后用read_excel()分别读取这两个工作表。
3. 有一个data.csv文件(内容:a,b,c\n1,2,3\n4,5,6\n7,8,9),用read_csv读取时:(a)不将第一行作为列名;(b)只读取第0列和第2列;(c)只读前2行。分别写出代码。
4. 模拟一个学生成绩CSV文件(包含姓名、语文、数学、英语四列,共10个学生),然后:(a)读取该文件;(b)计算每个学生的总分和平均分,新增为两列;(c)将结果写入新的Excel文件。
下一篇预告:《22 Matplotlib(一):绘图基础与常用图表》

浙公网安备 33010602011771号