数据读取与保存
Pandas 支持从多种数据源读取数据,也能将数据保存为各种格式。这是数据分析的第一步。
读取 CSV 文件
CSV(Comma-Separated Values)是最常见的数据格式之一。
基本读取
import pandas as pd
# 基本读取
df = pd.read_csv('data.csv')
# 查看数据
print(df.head())
print(df.shape)
常用参数
# 指定编码(处理中文)
df = pd.read_csv('data.csv', encoding='utf-8')
df = pd.read_csv('data.csv', encoding='gbk') # 中文 Windows 常用
# 指定分隔符
df = pd.read_csv('data.csv', sep=',') # 默认
df = pd.read_csv('data.tsv', sep='\t') # Tab 分隔
df = pd.read_csv('data.txt', sep='|') # 自定义分隔符
# 指定索引列
df = pd.read_csv('data.csv', index_col=0) # 第一列作为索引
df = pd.read_csv('data.csv', index_col='id') # 指定列名作为索引
df = pd.read_csv('data.csv', index_col=['year', 'month']) # 多列索引
# 解析日期
df = pd.read_csv('data.csv', parse_dates=['date'])
df = pd.read_csv('data.csv', parse_dates=[['year', 'month', 'day']])
# 指定数据类型
df = pd.read_csv('data.csv', dtype={'id': str, 'age': int})
# 读取特定列
df = pd.read_csv('data.csv', usecols=['name', 'age', 'salary'])
df = pd.read_csv('data.csv', usecols=[0, 2, 4]) # 按位置
# 跳过行
df = pd.read_csv('data.csv', skiprows=2) # 跳过前2行
df = pd.read_csv('data.csv', skiprows=[1, 3, 5]) # 跳过指定行
df = pd.read_csv('data.csv', skipfooter=1) # 跳过末尾行
# 读取前 N 行
df = pd.read_csv('data.csv', nrows=1000)
# 处理缺失值标记
df = pd.read_csv('data.csv', na_values=['NA', 'N/A', 'null', ''])
df = pd.read_csv('data.csv', na_values={'age': ['?'], 'salary': ['unknown']})
大文件处理
# 分块读取
chunk_size = 10000
chunks = []
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
# 处理每个块
processed = chunk[chunk['age'] > 18]
chunks.append(processed)
# 合并所有块
df = pd.concat(chunks, ignore_index=True)
# 使用迭代器
chunk_iter = pd.read_csv('large_file.csv', chunksize=10000)
first_chunk = next(chunk_iter)
读取 Excel 文件
基本读取
# 读取默认工作表
df = pd.read_excel('data.xlsx')
# 指定工作表
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
df = pd.read_excel('data.xlsx', sheet_name=0) # 按索引
# 读取多个工作表
all_sheets = pd.read_excel('data.xlsx', sheet_name=None) # 返回字典
print(all_sheets.keys()) # 查看所有工作表名
# 读取特定工作表列表
dfs = pd.read_excel('data.xlsx', sheet_name=['Sheet1', 'Sheet2'])
df1 = dfs['Sheet1']
df2 = dfs['Sheet2']
常用参数
# 指定行和列
df = pd.read_excel('data.xlsx', header=0) # 第0行为列名
df = pd.read_excel('data.xlsx', header=None) # 无列名
df = pd.read_excel('data.xlsx', names=['A', 'B', 'C']) # 自定义列名
df = pd.read_excel('data.xlsx', usecols='A:C') # 读取 A-C 列
df = pd.read_excel('data.xlsx', usecols=[0, 2, 4]) # 按位置
df = pd.read_excel('data.xlsx', skiprows=2) # 跳过前2行
# 其他参数与 read_csv 类似
df = pd.read_excel('data.xlsx',
index_col=0,
parse_dates=['date'],
dtype={'id': str})
读取 JSON 文件
# 从文件读取
df = pd.read_json('data.json')
# 从字符串读取
json_str = '[{"name": "张三", "age": 25}, {"name": "李四", "age": 30}]'
df = pd.read_json(json_str)
# 指定方向
df = pd.read_json('data.json', orient='records') # 默认
df = pd.read_json('data.json', orient='index')
df = pd.read_json('data.json', orient='columns')
# 从嵌套 JSON 读取
import json
with open('nested_data.json', 'r') as f:
data = json.load(f)
df = pd.json_normalize(data, record_path=['users'])
读取 SQL 数据库
import pandas as pd
from sqlalchemy import create_engine
# 创建连接
# MySQL
engine = create_engine('mysql+pymysql://user:password@host:port/database')
# PostgreSQL
engine = create_engine('postgresql://user:password@host:port/database')
# SQLite
engine = create_engine('sqlite:///database.db')
# 读取整个表
df = pd.read_sql('table_name', engine)
df = pd.read_sql_table('table_name', engine)
# 执行 SQL 查询
df = pd.read_sql('SELECT * FROM users WHERE age > 18', engine)
df = pd.read_sql_query('SELECT name, age FROM users', engine)
# 带参数查询
query = 'SELECT * FROM users WHERE age > %s AND city = %s'
df = pd.read_sql(query, engine, params=(18, '北京'))
# 分块读取
for chunk in pd.read_sql('SELECT * FROM large_table', engine, chunksize=10000):
process(chunk)
读取其他格式
HTML 表格
# 从 URL 读取表格
dfs = pd.read_html('https://example.com/data.html')
df = dfs[0] # 获取第一个表格
# 从本地文件读取
dfs = pd.read_html('data.html')
# 匹配特定表格
dfs = pd.read_html('data.html', match='特定文本')
Parquet 格式
# 读取 Parquet(高性能列式存储)
df = pd.read_parquet('data.parquet')
# 读取特定列
df = pd.read_parquet('data.parquet', columns=['name', 'age'])
HDF5 格式
# 读取 HDF5
df = pd.read_hdf('data.h5', key='df')
# 查看所有键
import h5py
with h5py.File('data.h5', 'r') as f:
print(list(f.keys()))
剪贴板
# 从剪贴板读取(复制 Excel 表格后)
df = pd.read_clipboard()
保存数据
保存为 CSV
# 基本保存
df.to_csv('output.csv')
# 常用参数
df.to_csv('output.csv',
index=False, # 不保存索引
encoding='utf-8', # 编码
sep=',', # 分隔符
na_rep='NULL', # 缺失值表示
float_format='%.2f', # 浮点数格式
columns=['name', 'age'], # 只保存特定列
header=True, # 是否保存列名
mode='w') # 写入模式
# 追加到文件
df.to_csv('output.csv', mode='a', header=False, index=False)
# 压缩保存
df.to_csv('output.csv.gz', compression='gzip')
df.to_csv('output.csv.zip', compression='zip')
保存为 Excel
# 基本保存
df.to_excel('output.xlsx')
# 保存到特定工作表
df.to_excel('output.xlsx', sheet_name='Sheet1')
# 保存多个 DataFrame
with pd.ExcelWriter('output.xlsx') as writer:
df1.to_excel(writer, sheet_name='数据1')
df2.to_excel(writer, sheet_name='数据2')
df3.to_excel(writer, sheet_name='数据3')
# 不保存索引
df.to_excel('output.xlsx', index=False)
# 从现有文件追加
with pd.ExcelWriter('existing.xlsx', mode='a', engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='新数据')
保存为 JSON
# 基本保存
df.to_json('output.json')
# 常用参数
df.to_json('output.json',
orient='records', # 格式
force_ascii=False, # 支持中文
indent=2) # 格式化缩进
# 不同 orient 格式
# 'records': [{"col1": 1, "col2": 2}, ...]
# 'index': {"0": {"col1": 1, "col2": 2}, ...}
# 'columns': {"col1": {"0": 1}, "col2": {"0": 2}}
# 'values': [[1, 2], [3, 4]]
# 'table': {"schema": ..., "data": ...}
保存到 SQL
# 保存到 SQL
df.to_sql('table_name', engine, if_exists='fail') # 如果表存在则报错
df.to_sql('table_name', engine, if_exists='replace') # 替换表
df.to_sql('table_name', engine, if_exists='append') # 追加数据
# 其他参数
df.to_sql('table_name',
engine,
if_exists='append',
index=False, # 不保存索引
chunksize=1000, # 分批写入
dtype={'name': sqlalchemy.types.VARCHAR(50),
'age': sqlalchemy.types.INTEGER()})
保存为其他格式
# Parquet(推荐用于大数据)
df.to_parquet('output.parquet')
df.to_parquet('output.parquet', compression='snappy')
# HDF5
df.to_hdf('output.h5', key='df', mode='w')
# Pickle(Python 对象序列化)
df.to_pickle('output.pkl')
df = pd.read_pickle('output.pkl')
# Markdown
df.to_markdown('output.md')
# LaTeX
print(df.to_latex())
实战示例
示例 1:数据迁移
# 从 MySQL 读取,保存到 PostgreSQL
mysql_engine = create_engine('mysql+pymysql://user:pass@localhost/db')
pg_engine = create_engine('postgresql://user:pass@localhost/db')
# 读取
df = pd.read_sql('SELECT * FROM users', mysql_engine)
# 转换(如果需要)
df['created_at'] = pd.to_datetime(df['created_at'])
# 保存
df.to_sql('users', pg_engine, if_exists='replace', index=False)
示例 2:Excel 报表生成
# 生成多工作表 Excel 报表
with pd.ExcelWriter('report.xlsx', engine='openpyxl') as writer:
# 汇总数据
summary.to_excel(writer, sheet_name='汇总', index=False)
# 明细数据
details.to_excel(writer, sheet_name='明细', index=False)
# 图表数据
chart_data.to_excel(writer, sheet_name='图表数据', index=False)
# 添加格式(需要 openpyxl)
workbook = writer.book
worksheet = writer.sheets['汇总']
# 调整列宽
worksheet.column_dimensions['A'].width = 20
worksheet.column_dimensions['B'].width = 15
示例 3:大文件处理
# 处理大 CSV 文件
def process_large_csv(input_file, output_file):
chunk_size = 50000
first_chunk = True
for chunk in pd.read_csv(input_file, chunksize=chunk_size):
# 数据清洗
chunk = chunk.dropna(subset=['important_column'])
chunk['new_column'] = chunk['column_a'] + chunk['column_b']
# 保存
if first_chunk:
chunk.to_csv(output_file, index=False, mode='w')
first_chunk = False
else:
chunk.to_csv(output_file, index=False, mode='a', header=False)
process_large_csv('large_input.csv', 'cleaned_output.csv')
格式对比
| 格式 | 读取函数 | 保存函数 | 特点 |
|---|---|---|---|
| CSV | read_csv | to_csv | 通用、文本格式 |
| Excel | read_excel | to_excel | 多工作表、格式丰富 |
| JSON | read_json | to_json | Web 常用、嵌套支持 |
| SQL | read_sql | to_sql | 数据库交互 |
| Parquet | read_parquet | to_parquet | 高性能、压缩 |
| HDF5 | read_hdf | to_hdf | 科学计算 |
| Pickle | read_pickle | to_pickle | Python 专用 |
| HTML | read_html | to_html | 网页表格 |
小结
读取数据的关键点:
- 了解数据源格式,选择合适的读取函数
- 注意编码问题(特别是中文)
- 大文件使用分块读取
- 正确解析日期和设置数据类型
保存数据的关键点:
- 根据使用场景选择格式
- 注意索引是否保存
- 考虑文件大小和读取性能
- 大数据量推荐使用 Parquet 格式
练习
- 读取一个 CSV 文件,处理后再保存为 Excel
- 从数据库读取数据,进行分组统计后保存为 JSON
- 处理一个大型 CSV 文件(使用分块读取)
- 生成包含多个工作表的 Excel 报表
下一步
学会了数据读取保存后,让我们学习 数据选择与过滤!