【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(一):绘图基础与常用图表》

posted @ 2026-06-27 08:45  AI视界尼奥  阅读(3)  评论(0)    收藏  举报