跳到主要内容

数据读取与保存

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')

格式对比

格式读取函数保存函数特点
CSVread_csvto_csv通用、文本格式
Excelread_excelto_excel多工作表、格式丰富
JSONread_jsonto_jsonWeb 常用、嵌套支持
SQLread_sqlto_sql数据库交互
Parquetread_parquetto_parquet高性能、压缩
HDF5read_hdfto_hdf科学计算
Pickleread_pickleto_picklePython 专用
HTMLread_htmlto_html网页表格

小结

读取数据的关键点

  • 了解数据源格式,选择合适的读取函数
  • 注意编码问题(特别是中文)
  • 大文件使用分块读取
  • 正确解析日期和设置数据类型

保存数据的关键点

  • 根据使用场景选择格式
  • 注意索引是否保存
  • 考虑文件大小和读取性能
  • 大数据量推荐使用 Parquet 格式

练习

  1. 读取一个 CSV 文件,处理后再保存为 Excel
  2. 从数据库读取数据,进行分组统计后保存为 JSON
  3. 处理一个大型 CSV 文件(使用分块读取)
  4. 生成包含多个工作表的 Excel 报表

下一步

学会了数据读取保存后,让我们学习 数据选择与过滤