Python CSV文件处理
CSV文件简介
CSV (Comma-Separated Values) 是一种简单的文件格式,用于存储表格数据。CSV文件是纯文本文件,其中每行表示表格中的一行,行内各个字段由逗号(或其他分隔符)分隔。由于CSV文件简单且通用,它们广泛用于不同系统和应用程序之间的数据交换。
CSV格式虽然简单,但没有正式标准,不同程序可能使用不同的分隔符(如逗号、制表符、分号等),或有不同的引号和转义规则。
Python 的CSV模块
Python标准库提供了csv
模块,使处理CSV文件变得简单高效。无论是读取、写入还是修改CSV文件,此模块都提供了必要的工具。
让我们开始学习如何使用Python处理CSV文件。
读取CSV文件
基本读取方法
首先,我们看看如何读取一个简单的CSV文件。假设我们有一个students.csv
文件,内容如下:
名字,年龄,班级
张三,15,高一(3)班
李四,16,高一(2)班
王五,15,高一(1)班
使用Python的csv
模块读取这个文件:
import csv
with open('students.csv', 'r', encoding='utf-8') as file:
csv_reader = csv.reader(file)
for row in csv_reader:
print(row)
输出结果:
['名字', '年龄', '班级']
['张三', '15', '高一(3)班']
['李四', '16', '高一(2)班']
['王五', '15', '高一(1)班']
注意,我们使用了encoding='utf-8'
参数来确保正确处理中文字符。
使用DictReader读取CSV
csv.DictReader
类使我们能够以字典形式访问每一行,其中列名被用作键:
import csv
with open('students.csv', 'r', encoding='utf-8') as file:
csv_reader = csv.DictReader(file)
for row in csv_reader:
print(f"{row['名字']} 是 {row['班级']} 的学生,今年 {row['年龄']} 岁")
输出结果:
张三 是 高一(3)班 的学生,今年 15 岁
李四 是 高一(2)班 的学生,今年 16 岁
王五 是 高一(1)班 的学生,今年 15 岁
写入CSV文件
基本写入方法
写入CSV文件非常直观,我们使用csv.writer
对象:
import csv
data = [
['姓名', '成绩', '科目'],
['张三', 89, '数学'],
['李四', 92, '语文'],
['王五', 95, '英语']
]
with open('scores.csv', 'w', encoding='utf-8', newline='') as file:
csv_writer = csv.writer(file)
for row in data:
csv_writer.writerow(row)
我们也可以使用writerows()
方法一次写入多行:
import csv
data = [
['姓名', '成绩', '科目'],
['张三', 89, '数学'],
['李四', 92, '语文'],
['王五', 95, '英语']
]
with open('scores.csv', 'w', encoding='utf-8', newline='') as file:
csv_writer = csv.writer(file)
csv_writer.writerows(data)
newline=''
参数可防止在Windows系统上出现空行。如果不添加这个参数,写入的CSV文件可能会在每行之间有额外的空行。
使用DictWriter写入CSV
与DictReader
类似,DictWriter
让我们可以使用字典写入CSV:
import csv
data = [
{'姓名': '张三', '成绩': 89, '科目': '数学'},
{'姓名': '李四', '成绩': 92, '科目': '语文'},
{'姓名': '王五', '成绩': 95, '科目': '英语'}
]
with open('scores_dict.csv', 'w', encoding='utf-8', newline='') as file:
fieldnames = ['姓名', '成绩', '科目']
csv_writer = csv.DictWriter(file, fieldnames=fieldnames)
# 写入表头
csv_writer.writeheader()
# 写入数据行
for row in data:
csv_writer.writerow(row)
高级CSV处理
处理不同的分隔符
如果CSV文件使用不同的分隔符(如分号、制表符等),你可以在创建reader
或writer
对象时指定:
import csv
# 读取使用分号分隔的CSV文件
with open('data.csv', 'r', encoding='utf-8') as file:
csv_reader = csv.reader(file, delimiter=';')
for row in csv_reader:
print(row)
# 写入使用制表符分隔的CSV文件
with open('output.csv', 'w', encoding='utf-8', newline='') as file:
csv_writer = csv.writer(file, delimiter='\t')
csv_writer.writerow(['Name', 'Age', 'Country'])
csv_writer.writerow(['John', 25, 'USA'])
处理引号和特殊字符
CSV文件中经常需要处理包含逗号、引号或其他特殊字符的数据。csv
模块提供了几种引号样式:
import csv
data = [
['Name', 'Quote'],
['John', 'He said, "Hello, world!"'],
['Mary', "She's coming tomorrow"]
]
with open('quotes.csv', 'w', encoding='utf-8', newline='') as file:
csv_writer = csv.writer(file, quoting=csv.QUOTE_ALL)
csv_writer.writerows(data)
输出的quotes.csv
文件将包含所有字段被引号包围:
"Name","Quote"
"John","He said, ""Hello, world!"""
"Mary","She's coming tomorrow"
csv
模块提供的引号常量包括:
csv.QUOTE_MINIMAL
: 仅在必要时使用引号(默认)csv.QUOTE_ALL
: 引用所有字段csv.QUOTE_NONNUMERIC
: 仅引用非数字字段csv.QUOTE_NONE
: 不使用引号
实际应用案例
案例1:学生成绩分析
想象我们有一个包含学生考试成绩的CSV文件exam_results.csv
:
学生ID,姓名,数学,语文,英语,物理,化学
1001,张三,85,92,78,91,87
1002,李四,92,78,85,76,88
1003,王五,78,95,92,84,81
1004,赵六,88,91,76,83,90
1005,钱七,95,82,89,94,86
我们可以编写Python脚本来计算每个学生的平均分和总分:
import csv
# 定义存储结果的列表
results = []
# 读取CSV文件
with open('exam_results.csv', 'r', encoding='utf-8') as file:
csv_reader = csv.DictReader(file)
for row in csv_reader:
# 提取学生信息
student_id = row['学生ID']
name = row['姓名']
# 计算总分和平均分
scores = [int(row['数学']), int(row['语文']), int(row['英语']),
int(row['物理']), int(row['化学'])]
total = sum(scores)
average = total / len(scores)
# 保存结果
results.append({
'学生ID': student_id,
'姓名': name,
'总分': total,
'平均分': round(average, 2)
})
# 按总分排序
results.sort(key=lambda x: x['总分'], reverse=True)
# 输出排名结果
print("排名\t学生ID\t姓名\t总分\t平均分")
for i, student in enumerate(results, 1):
print(f"{i}\t{student['学生ID']}\t{student['姓名']}\t{student['总分']}\t{student['平均分']}")
# 将结果写入新的CSV文件
with open('student_rankings.csv', 'w', encoding='utf-8', newline='') as file:
fieldnames = ['排名', '学生ID', '姓名', '总分', '平均分']
csv_writer = csv.DictWriter(file, fieldnames=fieldnames)
csv_writer.writeheader()
for i, student in enumerate(results, 1):
csv_writer.writerow({
'排名': i,
'学生ID': student['学生ID'],
'姓名': student['姓名'],
'总分': student['总分'],
'平均分': student['平均分']
})
案例2:数据清洗和转换
假设我们有一个包含一些产品销售数据的CSV文件,但数据格式不一致,需要清洗和转换:
import csv
# 读取原始CSV数据
sales_data = []
with open('raw_sales.csv', 'r', encoding='utf-8') as file:
csv_reader = csv.DictReader(file)
for row in csv_reader:
sales_data.append(row)
# 清洗和转换数据
cleaned_data = []
for item in sales_data:
# 处理缺失值
if not item['价格'] or item['价格'].strip() == '':
item['价格'] = '0'
# 统一格式(删除价格中的"¥"符号和空格)
price = item['价格'].replace('¥', '').replace(' ', '')
# 转换为数字格式
try:
price = float(price)
except ValueError:
price = 0
# 构建清洗后的记录
cleaned_record = {
'产品ID': item['产品ID'],
'产品名称': item['产品名称'],
'价格': price,
'销售日期': item['销售日期']
}
cleaned_data.append(cleaned_record)
# 将清洗后的数据写入新CSV文件
with open('cleaned_sales.csv', 'w', encoding='utf-8', newline='') as file:
fieldnames = ['产品ID', '产品名称', '价格', '销售日期']
csv_writer = csv.DictWriter(file, fieldnames=fieldnames)
csv_writer.writeheader()
csv_writer.writerows(cleaned_data)
print(f"数据清洗完成。处理了 {len(sales_data)} 条记录。")
CSV模块与Pandas
对于更复杂的CSV处理任务,尤其是数据分析,Python的Pandas库提供了更强大的功能:
import pandas as pd
# 读取CSV文件
df = pd.read_csv('students.csv')
# 查看前几行
print(df.head())
# 基本统计
print(df.describe())
# 写入CSV
df.to_csv('output.csv', index=False)
Pandas提供了过滤、转换、分组和聚合等高级功能,使得处理大型CSV文件变得容易。
总结
Python的csv
模块提供了处理CSV文件的简单而强大的工具:
csv.reader
和csv.writer
提供了基本的读写功能csv.DictReader
和csv.DictWriter
允许以字典形式处理数据- 参数如
delimiter
、quoting
等可以处理不同格式的CSV文件 - 对于更高级的数据处理和分析,可以考虑使用Pandas库
通过掌握这些知识,你可以有效地处理各种CSV数据处理任务,无论是简单的数据导入导出,还是复杂的数据清洗和分析。
练习题
- 创建一个简单的电话簿程序,可以读写CSV文件中的联系人信息(姓名、电话、邮箱)。
- 编写一个脚本,将两个不同格式的CSV文件合并为一个。
- 创建一个程序,读取一个CSV格式的支出记录,然后按类别汇总并生成报告。
处理CSV文件时,始终注意字符编码问题,尤其是当文件包含非ASCII字符时。推荐使用encoding='utf-8'
参数来避免编码错误。