一、csvkit 库概述
1.1 用途与工作原理
csvkit 是一套专门用于处理 CSV 文件的命令行工具和 Python 库,它能够帮助用户快速完成 CSV 文件的解析、转换、清洗、查询和统计分析等操作。无论是处理结构化的数据集,还是将其他格式(如 JSON、Excel、SQL 查询结果)转换为 CSV 格式,csvkit 都能提供简洁高效的解决方案。其工作原理是基于 Python 内置的 csv 模块进行封装扩展,同时结合了 agate 库(一个用于数据分析的 Python 库)的功能,实现对 CSV 数据的高效读写和数据类型推断,让用户无需编写复杂代码,通过简单的命令行指令或少量 Python 脚本就能完成数据处理任务。

1.2 优缺点分析
优点
- 操作便捷:提供丰富的命令行工具,无需编写大量 Python 代码即可完成常见 CSV 处理任务;
- 格式兼容:支持 CSV 与 JSON、Excel、SQL 等多种格式的相互转换;
- 数据类型推断:能够自动识别 CSV 文件中的数据类型(如整数、浮点数、日期等),避免手动指定类型的麻烦;
- 可扩展性强:既可以通过命令行使用,也可以作为 Python 库导入到项目中进行二次开发;
- 轻量高效:依赖较少,运行速度快,适合处理中小型规模的 CSV 数据集。
缺点
- 对超大规模 CSV 文件支持有限:当处理 GB 级以上的超大 CSV 文件时,内存占用较高,性能不如专门的大数据处理工具(如 Spark);
- 命令行工具学习成本:对于完全不熟悉命令行的用户,需要一定时间学习各个子命令的用法;
- 高级数据分析功能薄弱:相较于 Pandas 等专业数据分析库,csvkit 的统计分析和数据建模功能较为基础。
1.3 License 类型
csvkit 采用 MIT License 开源协议,这意味着用户可以自由地使用、复制、修改、合并、发布、分发、授权和/或销售本软件的副本,并且在软件副本中保留版权声明和许可声明即可,对个人和商业使用都非常友好。
二、csvkit 安装与环境配置
2.1 安装方式
csvkit 支持通过 pip 包管理工具一键安装,同时也可以从源码编译安装,以下是两种主流安装方法:
方法1:pip 安装(推荐)
打开命令行终端,执行以下命令即可完成安装:
pip install csvkit安装完成后,可以通过以下命令验证是否安装成功:
csvstat --version如果终端输出类似 csvstat 1.1.1 的版本信息,说明安装成功。
方法2:源码安装
如果需要安装最新的开发版本,可以从 GitHub 克隆源码并手动安装:
# 克隆仓库
git clone https://github.com/wireservice/csvkit.git
# 进入项目目录
cd csvkit
# 执行安装命令
pip install .2.2 依赖说明
csvkit 的核心依赖包括以下几个 Python 库,安装时会自动下载:
agate:用于数据读取、类型推断和基本统计分析;agate-excel:支持 Excel 文件(.xls、.xlsx)的读取和转换;agate-sql:支持与 SQL 数据库的交互,实现 CSV 与 SQL 表的转换;six:提供 Python 2 和 Python 3 的兼容性支持。
如果在安装过程中出现依赖缺失的问题,可以手动安装对应的依赖包:
pip install agate agate-excel agate-sql six三、csvkit 核心功能与使用示例
csvkit 包含多个命令行工具和 Python API,本节将分别介绍命令行工具的常用功能和 Python 脚本开发的使用方法,帮助技术小白快速上手。
3.1 命令行工具核心功能
csvkit 提供了十余个命令行工具,每个工具对应一个特定的 CSV 处理场景,以下是最常用的工具及其使用示例。
3.1.1 csvlook:格式化展示 CSV 数据
csvlook 工具可以将 CSV 文件以美观的表格形式输出到终端,方便用户快速预览数据结构,而无需打开 Excel 等软件。
基本语法
csvlook [选项] 输入文件.csv示例
假设我们有一个名为 students.csv 的文件,内容如下:
id,name,age,score,gender
1,Alice,18,95,female
2,Bob,19,88,male
3,Charlie,17,92,male
4,Diana,18,98,female在终端执行以下命令:
csvlook students.csv输出结果
| id | name | age | score | gender |
|-||--|-|--|
| 1 | Alice | 18 | 95 | female |
| 2 | Bob | 19 | 88 | male |
| 3 | Charlie | 17 | 92 | male |
| 4 | Diana | 18 | 98 | female |常用选项
-H:如果 CSV 文件没有表头,使用该选项指定;-y N:设置字符串类型的最大长度,超过部分会被截断;--no-headers:强制不使用表头。
3.1.2 csvstat:CSV 数据统计分析
csvstat 是 csvkit 中最实用的工具之一,它可以自动分析 CSV 文件的每一列数据,输出数据类型、非空值数量、唯一值数量、最小值、最大值、平均值等统计信息。
基本语法
csvstat [选项] 输入文件.csv示例
对 students.csv 执行统计命令:
csvstat students.csv输出结果
1. id
<type 'int'>
Nulls: False
Min: 1
Max: 4
Sum: 10
Mean: 2.5
Median: 2.5
Standard Deviation: 1.29099444874
Unique values: 4
5 most frequent values:
1: 1
2: 1
3: 1
4: 1
2. name
<type 'unicode'>
Nulls: False
Unique values: 4
5 most frequent values:
Alice: 1
Bob: 1
Charlie: 1
Diana: 1
3. age
<type 'int'>
Nulls: False
Min: 17
Max: 19
Sum: 72
Mean: 18
Median: 18
Standard Deviation: 0.816496580928
Unique values: 3
5 most frequent values:
18: 2
17: 1
19: 1
4. score
<type 'int'>
Nulls: False
Min: 88
Max: 98
Sum: 373
Mean: 93.25
Median: 93.5
Standard Deviation: 4.03112887415
Unique values: 4
5 most frequent values:
88: 1
92: 1
95: 1
98: 1
5. gender
<type 'unicode'>
Nulls: False
Unique values: 2
5 most frequent values:
female: 2
male: 2
Row count: 4常用选项
-c COLUMNS:指定要分析的列,例如-c 1,3表示只分析第1列和第3列;--json:将统计结果以 JSON 格式输出,方便后续处理;--freq N:设置显示最频繁值的数量,默认是5。
3.1.3 csvcut:CSV 数据列选择与裁剪
csvcut 工具用于选择 CSV 文件中的指定列,或者删除不需要的列,类似于 SQL 中的 SELECT 语句。
基本语法
csvcut [选项] 输入文件.csv示例1:选择指定列
从 students.csv 中选择 name 和 score 两列:
csvcut -c name,score students.csv输出结果
name,score
Alice,95
Bob,88
Charlie,92
Diana,98示例2:按列索引选择
CSV 文件的列索引从1开始,以下命令选择第1列(id)和第5列(gender):
csvcut -c 1,5 students.csv输出结果
id,gender
1,female
2,male
3,male
4,female示例3:排除指定列
使用 -x 选项排除不需要的列,例如排除 id 列:
csvcut -x -c id students.csv输出结果
name,age,score,gender
Alice,18,95,female
Bob,19,88,male
Charlie,17,92,male
Diana,18,98,female3.1.4 csvgrep:CSV 数据行过滤
csvgrep 工具用于根据指定条件过滤 CSV 文件中的行,类似于 SQL 中的 WHERE 子句。
基本语法
csvgrep [选项] 输入文件.csv常用选项
-c COLUMNS:指定要过滤的列;-m PATTERN:匹配等于指定模式的行;-r REGEX:使用正则表达式匹配行;-i:忽略大小写匹配。
示例1:精确匹配
从 students.csv 中筛选出 gender 为 female 的行:
csvgrep -c gender -m female students.csv输出结果
id,name,age,score,gender
1,Alice,18,95,female
4,Diana,18,98,female示例2:正则表达式匹配
筛选出 name 以字母 A 开头的行:
csvgrep -c name -r "^A" students.csv输出结果
id,name,age,score,gender
1,Alice,18,95,female3.1.5 in2csv:其他格式转换为 CSV
in2csv 工具可以将 Excel、JSON、TSV 等多种格式的文件转换为 CSV 格式,解决不同数据源的兼容性问题。
基本语法
in2csv [选项] 输入文件示例1:Excel 转 CSV
将名为 students.xlsx 的 Excel 文件转换为 CSV 格式:
in2csv students.xlsx > students_from_excel.csv示例2:JSON 转 CSV
假设有一个 students.json 文件,内容如下:
[
{"id": 1, "name": "Alice", "age": 18, "score": 95},
{"id": 2, "name": "Bob", "age": 19, "score": 88}
]执行以下命令转换为 CSV:
in2csv students.json > students_from_json.csv输出结果
id,name,age,score
1,Alice,18,95
2,Bob,19,88常用选项
-f FORMAT:指定输入文件格式,支持csv、excel、json等;--sheet SHEET_NAME:指定 Excel 文件中要转换的工作表名称。
3.1.6 csvsql:CSV 与 SQL 数据库交互
csvsql 工具允许用户直接对 CSV 文件执行 SQL 查询,或者将 CSV 文件导入到 SQL 数据库中(如 SQLite、MySQL、PostgreSQL)。
示例1:对 CSV 执行 SQL 查询
使用 SQL 语句从 students.csv 中查询分数大于90的学生信息:
csvsql --query "SELECT name, score FROM students WHERE score > 90" students.csv输出结果
name,score
Alice,95
Charlie,92
Diana,98示例2:将 CSV 导入 SQLite 数据库
创建一个 SQLite 数据库 students.db,并将 students.csv 导入为名为 students 的表:
csvsql --db sqlite:///students.db --insert students.csv执行完成后,可以使用 sqlite3 命令行工具连接数据库,查询数据:
sqlite3 students.db
sqlite> SELECT * FROM students WHERE gender = 'male';输出结果
3|Charlie|17|92|male
2|Bob|19|88|male3.2 Python 脚本开发:csvkit 库的 API 使用
除了命令行工具,csvkit 还可以作为 Python 库导入到脚本中,实现更灵活的 CSV 数据处理。csvkit 的 Python API 主要基于 agate 库的接口,以下是常用的使用示例。
3.2.1 读取 CSV 文件并获取数据
使用 csvkit 读取 CSV 文件后,可以通过行和列的索引访问数据,也可以遍历所有行。
# 导入必要的模块
from csvkit import CSVKitReader
from agate import Table
# 定义 CSV 文件路径
csv_file = "students.csv"
# 方法1:使用 CSVKitReader 读取 CSV
with open(csv_file, "r", encoding="utf-8") as f:
reader = CSVKitReader(f)
# 获取表头
headers = next(reader)
print("表头:", headers)
# 遍历数据行
print("数据行:")
for row in reader:
print(row)
# 方法2:使用 agate.Table 读取 CSV(推荐,支持数据类型推断)
table = Table.from_csv(csv_file)
# 输出表的基本信息
print("\n表的列数:", len(table.columns))
print("表的行数:", len(table.rows))
print("列名和数据类型:")
for column in table.columns:
print(f" {column.name}: {column.data_type}")代码说明
CSVKitReader是 csvkit 对 Python 内置csv.reader的封装,提供了基本的读取功能;agate.Table.from_csv()方法会自动推断每列的数据类型,返回一个Table对象,方便后续的统计分析;table.columns包含所有列的信息,table.rows包含所有数据行。
输出结果
表头: ['id', 'name', 'age', 'score', 'gender']
数据行:
['1', 'Alice', '18', '95', 'female']
['2', 'Bob', '19', '88', 'male']
['3', 'Charlie', '17', '92', 'male']
['4', 'Diana', '18', '98', 'female']
表的列数: 5
表的行数: 4
列名和数据类型:
id: Number
name: Text
age: Number
score: Number
gender: Text3.2.2 数据筛选与统计
通过 agate.Table 对象的方法,可以轻松实现数据筛选、排序和统计计算,无需编写复杂的循环逻辑。
from agate import Table
# 读取 CSV 文件
table = Table.from_csv("students.csv")
# 1. 数据筛选:筛选分数大于90的行
filtered_table = table.where(lambda row: row["score"] > 90)
print("分数大于90的学生:")
for row in filtered_table.rows:
print(f" {row['name']}: {row['score']}")
# 2. 数据排序:按年龄升序排序
sorted_table = table.order_by("age")
print("\n按年龄排序后的学生:")
for row in sorted_table.rows:
print(f" {row['name']}: {row['age']}")
# 3. 统计计算:计算平均分和总分
average_score = table.columns["score"].aggregate(table.aggregators.Mean())
total_score = table.columns["score"].aggregate(table.aggregators.Sum())
print(f"\n所有学生平均分:{average_score:.2f}")
print(f"所有学生总分:{total_score}")
# 4. 分组统计:按性别分组计算平均分
grouped_table = table.group_by("gender")
gender_avg_score = grouped_table.aggregate([
("average_score", table.aggregators.Mean("score"))
])
print("\n按性别分组的平均分:")
for row in gender_avg_score.rows:
print(f" {row['gender']}: {row['average_score']:.2f}")代码说明
table.where()方法接收一个 lambda 函数作为筛选条件,返回符合条件的新表;table.order_by()方法用于对数据进行排序,默认是升序,添加reverse=True参数可改为降序;table.columns["列名"].aggregate()方法用于对列数据进行统计计算,支持Mean、Sum、Max、Min等聚合函数;table.group_by()方法用于按指定列分组,结合aggregate()可以实现分组统计。
输出结果
分数大于90的学生:
Alice: 95
Charlie: 92
Diana: 98
按年龄排序后的学生:
Charlie: 17
Alice: 18
Diana: 18
Bob: 19
所有学生平均分:93.25
所有学生总分:373
按性别分组的平均分:
female: 96.50
male: 90.003.2.3 CSV 文件写入与格式转换
使用 csvkit 可以将处理后的数据写入新的 CSV 文件,也可以转换为 JSON、Excel 等格式。
from agate import Table
from csvkit.utilities.csvformat import CSVFormat
# 读取原始 CSV 文件
table = Table.from_csv("students.csv")
# 1. 筛选出女生数据并写入新的 CSV 文件
female_table = table.where(lambda row: row["gender"] == "female")
female_table.to_csv("female_students.csv")
print("女生数据已写入 female_students.csv")
# 2. 将数据转换为 JSON 格式并写入文件
female_table.to_json("female_students.json")
print("女生数据已转换为 JSON 格式并写入 female_students.json")
# 3. 自定义 CSV 格式写入(例如使用制表符分隔)
with open("female_students_tsv.tsv", "w", encoding="utf-8") as f:
writer = CSVFormat(f, delimiter="\t")
writer.writerow(female_table.column_names)
for row in female_table.rows:
writer.writerow(row)
print("女生数据已以制表符分隔格式写入 female_students_tsv.tsv")代码说明
table.to_csv()和table.to_json()是agate.Table对象的内置方法,可直接将数据写入对应格式的文件;CSVFormat类用于自定义 CSV 文件的格式,例如修改分隔符、换行符等,适合生成 TSV 等类 CSV 格式的文件。
执行上述代码后,会生成三个新文件:
female_students.csv:包含所有女生的信息;female_students.json:女生信息的 JSON 格式文件;female_students_tsv.tsv:以制表符分隔的女生信息文件。
四、实际案例:学生成绩数据分析与报告生成
本节将结合一个实际案例,展示如何使用 csvkit 的命令行工具和 Python 脚本,完成从 CSV 数据读取、清洗、分析到最终生成报告的完整流程。
4.1 案例背景
假设我们有一个包含多个班级学生成绩的 CSV 文件 class_scores.csv,内容如下:
class_id,student_id,name,chinese,math,english,total_score
1,101,Alice,85,92,88,265
1,102,Bob,78,85,90,253
1,103,Charlie,90,88,92,270
2,201,Diana,92,95,94,281
2,202,Ella,88,90,89,267
2,203,Frank,75,82,80,237
3,301,Grace,95,98,96,289
3,302,Henry,82,85,83,250
3,303,Ivy,88,92,90,270我们的目标是:
- 统计每个班级的平均分和最高分;
- 筛选出总分超过260分的学生;
- 生成一份包含统计结果的文本报告。
4.2 使用命令行工具快速分析
首先,我们使用 csvkit 的命令行工具完成基础的统计和筛选操作:
步骤1:查看数据结构
csvlook class_scores.csv快速预览数据的列结构和内容,确保数据格式正确。
步骤2:统计每个班级的平均分
使用 csvsql 执行分组统计 SQL 查询:
csvsql --query "SELECT class_id, AVG(total_score) as avg_score, MAX(total_score) as max_score FROM class_scores GROUP BY class_id ORDER BY class_id" class_scores.csv > class_stats.csv执行后生成 class_stats.csv 文件,内容为每个班级的平均分和最高分。
步骤3:筛选总分超过260分的学生
csvgrep -c total_score -r "^2[6-9][0-9]$|^2[0-9]{2}$" class_scores.csv | csvcut -c class_id,name,total_score > high_score_students.csv该命令筛选出总分在260-299之间的学生,并只保留班级ID、姓名和总分三列,结果保存到 high_score_students.csv。
4.3 使用 Python 脚本生成分析报告
接下来,我们使用 csvkit 的 Python API 读取统计结果,生成一份更详细的文本报告。
from agate import Table
# 读取班级统计数据和高分学生数据
class_stats_table = Table.from_csv("class_stats.csv")
high_score_table = Table.from_csv("high_score_students.csv")
# 生成报告内容
report_content = []
report_content.append("学生成绩分析报告")
report_content.append("=" * 30)
# 1. 班级统计信息
report_content.append("\n一、各班级总分统计")
for row in class_stats_table.rows:
report_content.append(f"班级 {row['class_id']}:")
report_content.append(f" 平均分:{row['avg_score']:.2f}")
report_content.append(f" 最高分:{row['max_score']}")
# 2. 高分学生统计
report_content.append("\n二、总分超过260分的学生名单")
report_content.append(f"总计:{len(high_score_table.rows)} 人")
for row in high_score_table.rows:
report_content.append(f" 班级 {row['class_id']} - {row['name']}:{row['total_score']} 分")
# 3. 计算全校平均分
all_scores_table = Table.from_csv("class_scores.csv")
school_avg = all_scores_table.columns["total_score"].aggregate(all_scores_table.aggregators.Mean())
report_content.append("\n三、全校总分平均分")
report_content.append(f" {school_avg:.2f} 分")
# 将报告写入文件
with open("score_analysis_report.txt", "w", encoding="utf-8") as f:
f.write("\n".join(report_content))
print("分析报告已生成:score_analysis_report.txt")代码说明
- 该脚本首先读取之前生成的
class_stats.csv和high_score_students.csv文件; - 然后通过字符串拼接的方式构建报告内容,包括班级统计、高分学生名单和全校平均分;
- 最后将报告写入
score_analysis_report.txt文件。
4.4 报告输出结果
生成的 score_analysis_report.txt 文件内容如下:
学生成绩分析报告
==============================
一、各班级总分统计
班级 1:
平均分:262.67
最高分:270
班级 2:
平均分:261.67
最高分:281
班级 3:
平均分:269.67
最高分:289
二、总分超过260分的学生名单
总计:6 人
班级 1 - Alice:265 分
班级 1 - Charlie:270 分
班级 2 - Diana:281 分
班级 2 - Ella:267 分
班级 3 - Grace:289 分
班级 3 - Ivy:270 分
三、全校总分平均分
264.67 分五、相关资源链接
- Pypi地址:https://pypi.org/project/csvkit
- Github地址:https://github.com/wireservice/csvkit
- 官方文档地址:https://csvkit.readthedocs.io/en/latest/
关注我,每天分享一个实用的Python自动化工具。

