0%

Python操作CSV文件完全指南

Python操作CSV文件完全指南

CSV(Comma-Separated Values,逗号分隔值)是一种简单、通用的数据交换格式,广泛应用于数据分析、数据迁移和自动化脚本中。Python提供了多种方式来操作CSV文件,从内置的csv模块到强大的第三方库如pandas和numpy。本文将详细介绍如何使用Python操作CSV文件,包括读取、写入、修改和分析CSV数据。

一、依赖的库

Python操作CSV文件主要依赖以下几个库:

1. csv(内置库)

csv是Python内置的CSV文件处理库,无需额外安装,适合处理简单的CSV文件。

2. pandas

pandas是一个强大的数据分析库,提供了高效的CSV文件读写和处理功能,适合处理大规模数据和复杂分析。

安装方法

1
pip install pandas

版本要求

  • 推荐版本:v2.2.4或更高

3. numpy

numpy是一个用于科学计算的库,也提供了CSV文件的读写功能,适合处理数值型数据。

安装方法

1
pip install numpy

版本要求

  • 推荐版本:v2.1.0或更高

二、使用Python内置csv模块操作CSV文件

1. 写入CSV文件

基本写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import csv

# 数据
rows = [
['姓名', '年龄', '城市'],
['张三', 28, '北京'],
['李四', 32, '上海'],
['王五', 25, '广州'],
['赵六', 35, '深圳']
]

# 写入CSV文件
with open('people.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerows(rows)

print("CSV文件写入成功!")

使用DictWriter写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import csv

# 数据
data = [
{'姓名': '张三', '年龄': 28, '城市': '北京'},
{'姓名': '李四', '年龄': 32, '城市': '上海'},
{'姓名': '王五', '年龄': 25, '城市': '广州'}
]

# 字段名
fields = ['姓名', '年龄', '城市']

# 写入CSV文件
with open('people_dict.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.DictWriter(file, fieldnames=fields)
writer.writeheader() # 写入表头
writer.writerows(data) # 写入数据

print("使用DictWriter写入CSV文件成功!")

2. 读取CSV文件

基本读取

1
2
3
4
5
6
7
import csv

# 读取CSV文件
with open('people.csv', 'r', encoding='utf-8') as file:
reader = csv.reader(file)
for row in reader:
print(row)

使用DictReader读取

1
2
3
4
5
6
7
import csv

# 读取CSV文件
with open('people_dict.csv', 'r', encoding='utf-8') as file:
reader = csv.DictReader(file)
for row in reader:
print(row['姓名'], row['年龄'], row['城市'])

3. 高级操作

指定分隔符

1
2
3
4
5
6
7
8
9
10
11
12
import csv

# 写入使用分号分隔的CSV文件
with open('people_semicolon.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file, delimiter=';')
writer.writerows(rows)

# 读取使用分号分隔的CSV文件
with open('people_semicolon.csv', 'r', encoding='utf-8') as file:
reader = csv.reader(file, delimiter=';')
for row in reader:
print(row)

处理引号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import csv

# 写入包含引号的数据
with open('quotes.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file, quoting=csv.QUOTE_ALL) # 所有字段加引号
writer.writerow(['姓名', '引言'])
writer.writerow(['张三', '"生活就像海洋"'])
writer.writerow(['李四', '"不经历风雨,怎么见彩虹"'])

# 读取包含引号的数据
with open('quotes.csv', 'r', encoding='utf-8') as file:
reader = csv.reader(file)
for row in reader:
print(row)

三、使用pandas库操作CSV文件

1. 读取CSV文件

基本读取

1
2
3
4
5
import pandas as pd

# 读取CSV文件
df = pd.read_csv('people.csv')
print(df)

读取指定列

1
2
3
# 读取指定列
df = pd.read_csv('people.csv', usecols=['姓名', '城市'])
print(df)

读取指定行数

1
2
3
# 读取前3行
df = pd.read_csv('people.csv', nrows=3)
print(df)

处理缺失值

1
2
3
4
5
6
7
# 读取CSV文件,将'NA'和'缺失'视为缺失值
df = pd.read_csv('people.csv', na_values=['NA', '缺失'])
print(df)

# 填充缺失值
df.fillna(0, inplace=True)
print(df)

设置索引列

1
2
3
# 使用'姓名'列作为索引
df = pd.read_csv('people.csv', index_col='姓名')
print(df)

2. 写入CSV文件

基本写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd

# 创建DataFrame
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [28, 32, 25, 35],
'城市': ['北京', '上海', '广州', '深圳']
}

df = pd.DataFrame(data)

# 写入CSV文件
df.to_csv('people_pandas.csv', index=False, encoding='utf-8')
print("使用pandas写入CSV文件成功!")

写入指定格式

1
2
3
4
5
# 写入CSV文件,设置保留两位小数
df.to_csv('people_format.csv', index=False, float_format='%.2f', encoding='utf-8')

# 写入CSV文件,使用分号分隔
df.to_csv('people_semicolon_pandas.csv', index=False, sep=';', encoding='utf-8')

3. 数据处理

筛选数据

1
2
3
4
5
6
7
# 筛选年龄大于30的数据
df_filtered = df[df['年龄'] > 30]
print(df_filtered)

# 筛选来自北京或上海的数据
df_filtered = df[df['城市'].isin(['北京', '上海'])]
print(df_filtered)

排序数据

1
2
3
4
5
6
7
# 按年龄升序排序
df_sorted = df.sort_values(by='年龄')
print(df_sorted)

# 按年龄降序排序
df_sorted = df.sort_values(by='年龄', ascending=False)
print(df_sorted)

分组统计

1
2
3
# 按城市分组,计算平均年龄
df_grouped = df.groupby('城市')['年龄'].mean()
print(df_grouped)

添加新列

1
2
3
# 添加新列
df['年龄分类'] = df['年龄'].apply(lambda x: '青年' if x < 30 else '中年')
print(df)

四、使用numpy库操作CSV文件

1. 读取CSV文件

基本读取

1
2
3
4
5
import numpy as np

# 读取CSV文件
data = np.genfromtxt('people.csv', delimiter=',', dtype=str)
print(data)

跳过表头

1
2
3
# 读取CSV文件,跳过表头
data = np.genfromtxt('people.csv', delimiter=',', dtype=str, skip_header=1)
print(data)

指定数据类型

1
2
3
4
5
6
7
# 读取CSV文件,指定数据类型
# 第一列是字符串,第二列是整数,第三列是字符串
data = np.genfromtxt('people.csv', delimiter=',', dtype=[('name', 'U10'), ('age', int), ('city', 'U10')], skip_header=1)
print(data)
print(data['name'])
print(data['age'])
print(data['city'])

2. 写入CSV文件

基本写入

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np

# 创建数据
data = np.array([
['姓名', '年龄', '城市'],
['张三', '28', '北京'],
['李四', '32', '上海'],
['王五', '25', '广州']
])

# 写入CSV文件
np.savetxt('people_numpy.csv', data, delimiter=',', fmt='%s', encoding='utf-8')
print("使用numpy写入CSV文件成功!")

写入数值数据

1
2
3
4
5
6
7
8
9
# 创建数值数据
numeric_data = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])

# 写入CSV文件,保留两位小数
np.savetxt('numeric_data.csv', numeric_data, delimiter=',', fmt='%.2f', encoding='utf-8')

五、完整代码示例

1. 示例1:使用csv模块管理学生成绩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import csv

# 学生成绩数据
students = [
{'姓名': '张三', '语文': 85, '数学': 92, '英语': 78},
{'姓名': '李四', '语文': 90, '数学': 88, '英语': 95},
{'姓名': '王五', '语文': 76, '数学': 85, '英语': 82},
{'姓名': '赵六', '语文': 92, '数学': 94, '英语': 89}
]

fields = ['姓名', '语文', '数学', '英语']

# 写入学生成绩到CSV文件
with open('students_scores.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.DictWriter(file, fieldnames=fields)
writer.writeheader()
writer.writerows(students)

print("学生成绩已写入CSV文件!")

# 读取并分析学生成绩
print("\n读取并分析学生成绩:")
total_scores = {}
subjects = ['语文', '数学', '英语']

with open('students_scores.csv', 'r', encoding='utf-8') as file:
reader = csv.DictReader(file)
for student in reader:
name = student['姓名']
total = sum(int(student[subj]) for subj in subjects)
avg = total / len(subjects)
total_scores[name] = {'总分': total, '平均分': avg}
print(f"{name}: 总分={total}, 平均分={avg:.2f}")

# 找出总分最高的学生
top_student = max(total_scores.items(), key=lambda x: x[1]['总分'])
print(f"\n总分最高的学生:{top_student[0]},总分={top_student[1]['总分']}")

2. 示例2:使用pandas分析销售数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import pandas as pd

# 创建销售数据
sales_data = {
'产品名称': ['A产品', 'B产品', 'C产品', 'A产品', 'B产品', 'C产品'],
'销售日期': ['2026-01-01', '2026-01-01', '2026-01-01', '2026-01-02', '2026-01-02', '2026-01-02'],
'销售数量': [100, 150, 200, 120, 180, 220],
'销售金额': [5000, 7500, 10000, 6000, 9000, 11000]
}

df = pd.DataFrame(sales_data)

# 写入CSV文件
df.to_csv('sales_data.csv', index=False, encoding='utf-8')

print("销售数据已写入CSV文件!")

# 读取销售数据
df_sales = pd.read_csv('sales_data.csv', encoding='utf-8')
print("\n销售数据:")
print(df_sales)

# 数据分析
print("\n数据分析:")

# 1. 按产品分组,计算总销售数量和总销售金额
product_sales = df_sales.groupby('产品名称')[['销售数量', '销售金额']].sum()
print("按产品分组的销售情况:")
print(product_sales)

# 2. 按日期分组,计算总销售金额
date_sales = df_sales.groupby('销售日期')['销售金额'].sum()
print("\n按日期分组的销售金额:")
print(date_sales)

# 3. 计算每个产品的平均销售单价
df_sales['单价'] = df_sales['销售金额'] / df_sales['销售数量']
avg_price = df_sales.groupby('产品名称')['单价'].mean()
print("\n每个产品的平均销售单价:")
print(avg_price)

# 4. 找出销售数量最多的产品
top_product = df_sales.groupby('产品名称')['销售数量'].sum().idxmax()
top_sales = df_sales.groupby('产品名称')['销售数量'].sum().max()
print(f"\n销售数量最多的产品:{top_product},销售数量={top_sales}")

六、常见错误及解决方案

1. 编码错误

错误信息UnicodeDecodeError: 'gbk' codec can't decode byte 0xa0 in position 20: illegal multibyte sequence

解决方案

  • 在打开文件时指定正确的编码,如encoding='utf-8'encoding='gbk'
  • 使用errors='ignore'忽略无法解码的字符(不推荐)
  • 使用chardet库检测文件编码:
    1
    2
    3
    4
    5
    import chardet

    with open('file.csv', 'rb') as f:
    result = chardet.detect(f.read())
    print(result['encoding']) # 输出文件编码

2. 分隔符错误

错误信息ValueError: Expected 3 fields in line 2, saw 5

解决方案

  • 检查CSV文件的分隔符是否正确
  • 在读取文件时指定正确的分隔符,如delimiter=';'delimiter='\t'
  • 使用csv.Sniffer自动检测分隔符:
    1
    2
    3
    4
    5
    6
    import csv

    with open('file.csv', 'r', encoding='utf-8') as f:
    dialect = csv.Sniffer().sniff(f.read(1024))
    f.seek(0) # 重置文件指针
    reader = csv.reader(f, dialect)

3. 字段名不匹配

错误信息KeyError: '字段名'

解决方案

  • 检查CSV文件的表头是否正确
  • 使用reader.fieldnames查看实际的字段名
  • 确保代码中使用的字段名与CSV文件中的表头一致

4. 类型转换错误

错误信息ValueError: invalid literal for int() with base 10: '字符串'

解决方案

  • 在转换数据类型前检查数据格式
  • 使用try-except处理异常值:
    1
    2
    3
    4
    try:
    age = int(row['年龄'])
    except ValueError:
    age = 0 # 或其他默认值
  • 使用pandas的pd.to_numeric()函数安全转换:
    1
    df['年龄'] = pd.to_numeric(df['年龄'], errors='coerce')

5. 文件路径错误

错误信息FileNotFoundError: [Errno 2] No such file or directory: 'file.csv'

解决方案

  • 检查文件路径是否正确
  • 使用绝对路径代替相对路径
  • 确保文件存在于指定位置

七、最佳实践

  1. 选择合适的库

    • 对于简单的CSV操作,使用内置的csv模块
    • 对于数据分析和处理,使用pandas
    • 对于数值型数据,使用numpy
  2. 使用上下文管理器

    • 始终使用with语句打开文件,确保文件正确关闭
    • 避免手动打开和关闭文件,减少资源泄漏风险
  3. 指定编码

    • 打开文件时明确指定编码,如encoding='utf-8'
    • 确保写入和读取使用相同的编码
  4. 处理缺失值

    • 在读取CSV文件时,指定缺失值标记
    • 对缺失值进行适当处理,如填充默认值或删除
  5. 优化性能

    • 对于大型CSV文件,使用pandas的chunksize参数分块读取
    • 避免在循环中频繁读写文件
    • 使用向量化操作代替循环
  6. 数据验证

    • 在写入CSV文件前验证数据格式
    • 在读取CSV文件后检查数据完整性
    • 使用类型注解提高代码可读性和可维护性
  7. 文档和注释

    • 为CSV文件添加说明文档
    • 在代码中添加注释,说明数据格式和处理逻辑
    • 保存数据字典,说明每个字段的含义和格式

八、总结

本文详细介绍了Python操作CSV文件的三种主要方式:

  1. 内置csv模块:适合简单的CSV读写操作,无需额外安装库,使用方便
  2. pandas库:适合大规模数据处理和分析,提供了丰富的数据操作功能
  3. numpy库:适合数值型数据的读写,性能高效

通过学习本文,你应该能够:

  • 使用不同的库读写CSV文件
  • 处理不同格式的CSV数据
  • 进行基本的数据清洗和分析
  • 解决常见的CSV操作错误
  • 遵循最佳实践编写高效、可靠的CSV处理代码

CSV文件作为一种简单、通用的数据格式,在数据处理和分析中扮演着重要角色。掌握Python操作CSV文件的技能,将有助于你更高效地处理各种数据任务,提高工作效率。

九、参考资料

  1. Python官方文档 - csv模块
  2. pandas官方文档 - CSV读写
  3. numpy官方文档 - CSV读写
  4. Real Python - Working with CSV Files in Python
  5. W3Schools - Python CSV
  6. CSV文件格式规范
  7. Python数据分析实战

欢迎关注我的其它发布渠道