Module 7: 文件输入输出 (File I/O)
数据持久化的必备技能 —— 读写各种格式的数据文件
本章概览
数据分析的第一步是读取数据,最后一步是保存结果。本章将教你如何在 Python 中读写各种格式的文件:文本文件、CSV、Excel、Stata(.dta)、JSON 等。掌握文件 I/O,你就能与各种数据源无缝对接。
重要提示:本章是数据分析的基础设施,虽然不如回归分析有趣,但却是必不可少的技能。
学习目标
学完本章后,你将能够:
- 理解文件路径和编码问题
- 读写文本文件(
.txt) - 处理 CSV 文件(最常用的数据格式)
- 读写 Excel 文件(
.xlsx) - 与 Stata 数据无缝对接(
.dta) - 处理 JSON 数据(API 和 Web 数据)
- 批量处理多个文件
- 构建数据处理流水线
章节内容
01 - 文件读写基础
核心问题: 如何读写文本文件?
核心内容:
- 为什么需要文件操作?
- 保存数据分析结果
- 读取外部数据
- 生成报告和日志
- 数据备份
- 基本文件操作:
- 写入文件:
open('file.txt', 'w') - 读取文件:
open('file.txt', 'r') - 追加内容:
open('file.txt', 'a')
- 写入文件:
- 上下文管理器(with 语句):python
# 推荐(自动关闭文件) with open('file.txt', 'r', encoding='utf-8') as f: content = f.read() # 不推荐(需要手动关闭) f = open('file.txt', 'r') content = f.read() f.close() - 路径操作(pathlib):python
from pathlib import Path data_dir = Path('data') raw_dir = data_dir / 'raw' # 路径拼接 raw_dir.mkdir(parents=True, exist_ok=True) # 创建目录 for file in data_dir.glob('*.txt'): # 遍历文件 print(file) - 编码问题:
- 中文文件必须指定
encoding='utf-8' - Windows 默认编码是
gbk,可能导致乱码
- 中文文件必须指定
实战案例:
# 案例:保存问卷结果
respondents = [
{'id': 1001, 'age': 25, 'income': 50000},
{'id': 1002, 'age': 30, 'income': 75000}
]
with open('survey_results.txt', 'w', encoding='utf-8') as f:
f.write("问卷调查结果\n")
f.write("=" * 40 + "\n")
for resp in respondents:
line = f"ID:{resp['id']}, 年龄:{resp['age']}, 收入:{resp['income']}\n"
f.write(line)02 - CSV 与 Excel 文件处理
核心问题: 如何读写表格数据?
核心内容:
- CSV 文件(最常用):
- 使用
csv模块(基础) - 使用 Pandas(推荐):python
import pandas as pd # 读取 CSV df = pd.read_csv('survey.csv') # 写入 CSV(避免 Excel 乱码) df.to_csv('output.csv', index=False, encoding='utf-8-sig') # 常用参数 df = pd.read_csv( 'data.csv', sep=',', # 分隔符 header=0, # 第一行是列名 usecols=[0, 1, 3], # 只读某些列 dtype={'age': int}, # 指定数据类型 na_values=['NA', ''] # 缺失值标记 )
- 使用
- Excel 文件:
- 安装依赖:
pip install openpyxl - 读取单个工作表:python
df = pd.read_excel('survey.xlsx', sheet_name='Sheet1') - 读取多个工作表:python
all_sheets = pd.read_excel('survey.xlsx', sheet_name=None) - 写入多个工作表:python
with pd.ExcelWriter('report.xlsx') as writer: df1.to_excel(writer, sheet_name='2023', index=False) df2.to_excel(writer, sheet_name='2024', index=False)
- 安装依赖:
实战案例:
# 案例:合并多个 CSV 文件
from pathlib import Path
data_dir = Path('surveys')
all_data = []
for csv_file in data_dir.glob('*.csv'):
df = pd.read_csv(csv_file)
df['source_file'] = csv_file.name # 添加来源标识
all_data.append(df)
combined_df = pd.concat(all_data, ignore_index=True)
combined_df.to_csv('combined_survey.csv', index=False)03 - Stata 数据文件读写
核心问题: 如何与 Stata 数据无缝对接?
核心内容:
- 为什么需要读写 Stata 文件?
- 很多社科数据以
.dta格式存储 - 保留变量标签、值标签等元数据
- 与 Stata 用户协作
- 很多社科数据以
- 读取 Stata 文件:python
import pandas as pd # 基本读取 df = pd.read_stata('survey_data.dta') # 保留值标签(例如:1='Male', 2='Female') df = pd.read_stata('survey_data.dta', convert_categoricals=True) - 写入 Stata 文件:python
# 保存为 Stata 13 格式 df.to_stata('output.dta', write_index=False, version=117) # Stata 版本对照: # 117 = Stata 13/14 # 118 = Stata 15/16 # 119 = Stata 17 - 处理变量标签和值标签:python
# 添加变量标签 variable_labels = { 'id': 'Respondent ID', 'gender': 'Gender', 'education': 'Education Level' } df.to_stata( 'output.dta', write_index=False, variable_labels=variable_labels )
实战案例:
# 案例:Stata 到 Python 数据流
import pandas as pd
import numpy as np
# 1. 读取 Stata 数据
df = pd.read_stata('raw_survey.dta')
print(f"原始数据: {len(df)} 行")
# 2. 数据清洗(Python)
df_clean = df[
(df['age'] >= 18) &
(df['age'] <= 100) &
(df['income'] > 0)
].copy()
# 3. 新变量生成
df_clean['log_income'] = np.log(df_clean['income'])
df_clean['age_squared'] = df_clean['age'] ** 2
# 4. 保存回 Stata 格式
df_clean.to_stata('clean_survey.dta', write_index=False)
print(f"清洗后: {len(df_clean)} 行")04 - JSON 数据处理
核心问题: 如何处理 Web 和 API 数据?
核心内容:
- 什么是 JSON?
- 现代 Web 数据的标准格式
- 结构类似 Python 字典
- 广泛用于 API、配置文件
- 基本操作:python
import json # Python 对象 → JSON 字符串 data = {'id': 1001, 'age': 30, 'income': 75000} json_str = json.dumps(data, indent=2, ensure_ascii=False) # JSON 字符串 → Python 对象 json_str = '{"name": "Alice", "age": 25}' data = json.loads(json_str) # 读写 JSON 文件 with open('data.json', 'w', encoding='utf-8') as f: json.dump(data, f, indent=2, ensure_ascii=False) with open('data.json', 'r', encoding='utf-8') as f: data = json.load(f) - JSON 与 Pandas 互转:python
# Pandas → JSON df.to_json('data.json', orient='records', force_ascii=False, indent=2) # JSON → Pandas df = pd.read_json('data.json', orient='records')
实战案例:
# 案例:从 API 获取数据
import requests
import pandas as pd
# 1. 获取 JSON 数据
response = requests.get('https://api.example.com/data')
data = response.json()
# 2. 转为 DataFrame
df = pd.DataFrame(data['results'])
# 3. 保存为 CSV
df.to_csv('api_data.csv', index=False)文件格式对比
| 格式 | 优点 | 缺点 | 使用场景 |
|---|---|---|---|
| TXT | 简单、通用 | 无结构 | 日志、简单报告 |
| CSV | 通用、轻量、易读 | 无类型信息、无元数据 | 数据交换、表格数据 |
| Excel | 多工作表、格式丰富 | 文件大、速度慢 | 报告、给非技术人员 |
| Stata(.dta) | 保留标签、元数据 | 仅社科领域使用 | 社科数据、与 Stata 协作 |
| JSON | 结构化、嵌套数据 | 体积大 | API 数据、配置文件 |
| Parquet | 高效、压缩好 | 不可读 | 大数据、生产环境 |
选择建议
| 需求 | 推荐格式 | 原因 |
|---|---|---|
| 数据交换 | CSV | 通用、所有工具都支持 |
| 给导师/同事 | Excel | 可视化好、易编辑 |
| Stata 协作 | DTA | 保留元数据 |
| API 数据 | JSON | 标准格式 |
| 大数据(>1GB) | Parquet | 高效、压缩好 |
| 中间结果 | CSV/Pickle | 快速、简单 |
如何学习本章?
学习路线
第 1 天(2小时): 文件读写基础
- 阅读 01 - 文件读写基础
- 练习读写文本文件
- 学习 pathlib 路径操作
第 2 天(3小时): CSV 与 Excel
- 阅读 02 - CSV 与 Excel 文件处理
- 用 Pandas 读写 CSV
- 练习合并多个 CSV 文件
第 3 天(2小时): Stata 数据
- 阅读 03 - Stata 数据文件读写
- 读取
.dta文件 - 练习 Stata ↔ Python 数据流
第 4 天(2小时): JSON 数据
- 阅读 04 - JSON 数据处理
- 练习 JSON 读写
- JSON 与 Pandas 互转
总时间: 9 小时(1 周)
最小化学习路径
对于社科学生,优先级如下:
必学(日常分析,5小时):
- 02 - CSV 与 Excel(最常用)
- 03 - Stata 数据文件(社科必备)
- Pandas 读写基础
重要(完整技能,4小时):
- 01 - 文件读写基础
- 04 - JSON 数据处理
可选(高级主题):
- 批量处理多个文件
- Parquet、HDF5 等高效格式
- 数据库连接(SQL)
学习建议
以实际需求为导向
- 有什么格式的数据,就学对应的方法
- CSV 和 Stata 是社科学生的重点
- JSON 在使用 API 时才需要
记住核心模式
python# 几乎所有格式都遵循这个模式: # 读取 data = pd.read_xxx('file.xxx') # 处理 data_clean = data[data['age'] > 18] # 保存 data_clean.to_xxx('output.xxx')常见错误和解决方案
- 乱码: 指定
encoding='utf-8'或encoding='utf-8-sig' - 文件未找到: 检查路径,使用绝对路径或
Path() - 缺失值: 指定
na_values=['NA', '', '-999'] - 数据类型: 使用
dtype={'col': int}指定类型
- 乱码: 指定
实践项目 创建一个数据处理流水线:
python# data_pipeline.py import pandas as pd from pathlib import Path def process_survey(input_file, output_file): """处理问卷数据""" # 1. 读取 df = pd.read_stata(input_file) print(f"原始数据: {len(df)} 行") # 2. 清洗 df_clean = df[ (df['age'] >= 18) & (df['age'] <= 100) & (df['income'] > 0) ] print(f"清洗后: {len(df_clean)} 行") # 3. 保存 df_clean.to_csv(output_file, index=False, encoding='utf-8-sig') print(f"已保存到: {output_file}") # 使用 process_survey('raw_survey.dta', 'clean_survey.csv')
常见问题
Q: 为什么读取中文 CSV 会乱码? A: 编码问题。尝试:
# 方法 1:UTF-8
df = pd.read_csv('data.csv', encoding='utf-8')
# 方法 2:GBK(Windows 中文)
df = pd.read_csv('data.csv', encoding='gbk')
# 方法 3:自动检测
df = pd.read_csv('data.csv', encoding='utf-8-sig')Q: 为什么保存的 CSV 用 Excel 打开是乱码? A: Excel 默认用 GBK 编码打开文件。解决方案:
# 保存时使用 utf-8-sig(Excel 兼容的 UTF-8)
df.to_csv('output.csv', index=False, encoding='utf-8-sig')Q: 如何处理大文件(>1GB)? A: 分块读取:
# 分块读取
for chunk in pd.read_csv('large_file.csv', chunksize=10000):
# 处理每个 chunk
processed = chunk[chunk['age'] > 18]
# 保存或进一步处理Q: Stata 和 CSV 哪个好? A:
- Stata(.dta): 保留变量标签和值标签,适合社科数据
- CSV: 通用格式,所有工具都支持,但丢失元数据
- 建议: 原始数据用 Stata,中间结果用 CSV
Q: 为什么推荐 Pandas 而不是 csv 模块? A:
- Pandas 更强大:自动类型推断、缺失值处理、数据操作
- csv 模块更底层:需要手动处理很多细节
- 对于数据分析,Pandas 是首选
Q: 如何批量处理多个文件? A:
from pathlib import Path
data_dir = Path('surveys')
for file in data_dir.glob('*.csv'):
df = pd.read_csv(file)
# 处理...
df.to_csv(f'processed_{file.name}', index=False)下一步
完成本章后,你将掌握:
- 读写文本、CSV、Excel、Stata、JSON 文件
- 处理编码和路径问题
- 批量处理多个文件
- 构建数据处理流水线
在 Module 8 中,我们将学习错误处理和调试,让代码更健壮可靠。
在 Module 9 中,我们将深入学习 NumPy、Pandas、Matplotlib 等数据科学核心库。
掌握文件 I/O,你就能处理任何数据源了!继续前进!