Pandas 数据读取与写入(IO 操作)详细总结

第四章:数据读取与写入(IO 操作)

🎯 目标:掌握从各种数据源读取数据和保存数据的方法,打通数据流通的任督二脉。


1.1 为什么需要 IO 操作?

1.1.1 数据在哪里?

在现实工作中,数据分散在各个角落:
#mermaid-svg-WRs3NRDVP7ilha2D{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WRs3NRDVP7ilha2D .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WRs3NRDVP7ilha2D .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WRs3NRDVP7ilha2D .error-icon{fill:#552222;}#mermaid-svg-WRs3NRDVP7ilha2D .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WRs3NRDVP7ilha2D .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WRs3NRDVP7ilha2D .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WRs3NRDVP7ilha2D .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WRs3NRDVP7ilha2D .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WRs3NRDVP7ilha2D .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WRs3NRDVP7ilha2D .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WRs3NRDVP7ilha2D .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WRs3NRDVP7ilha2D .marker.cross{stroke:#333333;}#mermaid-svg-WRs3NRDVP7ilha2D svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WRs3NRDVP7ilha2D p{margin:0;}#mermaid-svg-WRs3NRDVP7ilha2D .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WRs3NRDVP7ilha2D .cluster-label text{fill:#333;}#mermaid-svg-WRs3NRDVP7ilha2D .cluster-label span{color:#333;}#mermaid-svg-WRs3NRDVP7ilha2D .cluster-label span p{background-color:transparent;}#mermaid-svg-WRs3NRDVP7ilha2D .label text,#mermaid-svg-WRs3NRDVP7ilha2D span{fill:#333;color:#333;}#mermaid-svg-WRs3NRDVP7ilha2D .node rect,#mermaid-svg-WRs3NRDVP7ilha2D .node circle,#mermaid-svg-WRs3NRDVP7ilha2D .node ellipse,#mermaid-svg-WRs3NRDVP7ilha2D .node polygon,#mermaid-svg-WRs3NRDVP7ilha2D .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WRs3NRDVP7ilha2D .rough-node .label text,#mermaid-svg-WRs3NRDVP7ilha2D .node .label text,#mermaid-svg-WRs3NRDVP7ilha2D .image-shape .label,#mermaid-svg-WRs3NRDVP7ilha2D .icon-shape .label{text-anchor:middle;}#mermaid-svg-WRs3NRDVP7ilha2D .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WRs3NRDVP7ilha2D .rough-node .label,#mermaid-svg-WRs3NRDVP7ilha2D .node .label,#mermaid-svg-WRs3NRDVP7ilha2D .image-shape .label,#mermaid-svg-WRs3NRDVP7ilha2D .icon-shape .label{text-align:center;}#mermaid-svg-WRs3NRDVP7ilha2D .node.clickable{cursor:pointer;}#mermaid-svg-WRs3NRDVP7ilha2D .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WRs3NRDVP7ilha2D .arrowheadPath{fill:#333333;}#mermaid-svg-WRs3NRDVP7ilha2D .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WRs3NRDVP7ilha2D .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WRs3NRDVP7ilha2D .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WRs3NRDVP7ilha2D .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WRs3NRDVP7ilha2D .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WRs3NRDVP7ilha2D .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WRs3NRDVP7ilha2D .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WRs3NRDVP7ilha2D .cluster text{fill:#333;}#mermaid-svg-WRs3NRDVP7ilha2D .cluster span{color:#333;}#mermaid-svg-WRs3NRDVP7ilha2D div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WRs3NRDVP7ilha2D .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WRs3NRDVP7ilha2D rect.text{fill:none;stroke-width:0;}#mermaid-svg-WRs3NRDVP7ilha2D .icon-shape,#mermaid-svg-WRs3NRDVP7ilha2D .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WRs3NRDVP7ilha2D .icon-shape p,#mermaid-svg-WRs3NRDVP7ilha2D .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WRs3NRDVP7ilha2D .icon-shape .label rect,#mermaid-svg-WRs3NRDVP7ilha2D .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WRs3NRDVP7ilha2D .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WRs3NRDVP7ilha2D .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WRs3NRDVP7ilha2D :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 你的分析任务
CSV 文件
Excel 表格
数据库
JSON API
Parquet 文件
Pandas DataFrame
分析结果
保存到文件
写入数据库
生成报告

IO 操作 = 数据的"进口"和"出口"


1.2 CSV 文件操作

1.2.1 读取 CSV(read_csv)

CSV(Comma-Separated Values)是最常见的数据格式。

python 复制代码
import pandas as pd

# 🌟 基础读取
df = pd.read_csv('data.csv')

# 🌟 指定编码(处理中文乱码)
df = pd.read_csv('data.csv', encoding='utf-8')      # UTF-8 编码
df = pd.read_csv('data.csv', encoding='gbk')        # 中文 Windows 常用
df = pd.read_csv('data.csv', encoding='gb2312')     # 国标编码

# 🌟 指定分隔符(默认是逗号)
df = pd.read_csv('data.txt', sep='\t')     # Tab 分隔
df = pd.read_csv('data.csv', sep=';')      # 分号分隔
df = pd.read_csv('data.csv', sep='|')      # 竖线分隔

# 🌟 指定列名(如果文件没有表头)
df = pd.read_csv('data.csv', header=None)  # 没有表头
df = pd.read_csv('data.csv', header=None, names=['姓名', '年龄', '城市'])  # 自定义列名

# 🌟 指定索引列
df = pd.read_csv('data.csv', index_col=0)           # 第1列作为索引
df = pd.read_csv('data.csv', index_col='姓名')       # 指定列名作为索引
df = pd.read_csv('data.csv', index_col=['部门', '姓名'])  # 多级索引

# 🌟 只读取部分列
df = pd.read_csv('data.csv', usecols=['姓名', '年龄', '月薪'])
df = pd.read_csv('data.csv', usecols=[0, 2, 4])      # 按位置选择列

# 🌟 只读取前 N 行
df = pd.read_csv('data.csv', nrows=1000)

# 🌟 跳过前 N 行
df = pd.read_csv('data.csv', skiprows=5)

# 🌟 处理大文件(分块读取)
chunk_size = 10000
for chunk in pd.read_csv('big_data.csv', chunksize=chunk_size):
    # 每次处理 10000 行
    print(f"处理 {len(chunk)} 行数据")
    # 在这里进行数据处理...

1.2.2 写入 CSV(to_csv)

python 复制代码
# 🌟 基础写入
df.to_csv('output.csv', index=False)  # 不保存行索引

# 🌟 完整参数
df.to_csv(
    'output.csv',
    index=False,          # 不保存行索引
    encoding='utf-8',     # 编码
    sep=',',              # 分隔符
    na_rep='NULL',        # 缺失值显示为 NULL
    float_format='%.2f',  # 浮点数保留2位小数
    columns=['姓名', '年龄'],  # 只保存指定列
    header=True,          # 保存列名
    mode='w'              # 写入模式('w'覆盖,'a'追加)
)

# 🌟 追加到已有文件
df_new.to_csv('output.csv', mode='a', header=False, index=False)

1.2.3 CSV 最佳实践

python 复制代码
# ✅ 推荐:读取时处理好编码和索引
df = pd.read_csv(
    'data.csv',
    encoding='utf-8',
    index_col='id',
    parse_dates=['日期'],      # 自动解析日期列
    dtype={'类别': 'category'}  # 指定列的数据类型
)

# ✅ 推荐:写入时不保存索引,避免重复列
df.to_csv('output.csv', index=False, encoding='utf-8-sig')  # utf-8-sig 让 Excel 正确识别中文

1.3 Excel 文件操作

1.3.1 读取 Excel(read_excel)

python 复制代码
# 🌟 基础读取(默认读取第一个 Sheet)
df = pd.read_excel('data.xlsx')

# 🌟 读取指定 Sheet
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')      # 按名称
df = pd.read_excel('data.xlsx', sheet_name=0)              # 按位置(从0开始)
df = pd.read_excel('data.xlsx', sheet_name=['Sheet1', 'Sheet2'])  # 读取多个 Sheet

# 🌟 读取所有 Sheet(返回字典)
all_sheets = pd.read_excel('data.xlsx', sheet_name=None)
print(all_sheets.keys())  # dict_keys(['Sheet1', 'Sheet2', 'Sheet3'])
df1 = all_sheets['Sheet1']

# 🌟 指定行作为表头
df = pd.read_excel('data.xlsx', header=0)   # 第1行作为表头(默认)
df = pd.read_excel('data.xlsx', header=1)   # 第2行作为表头
df = pd.read_excel('data.xlsx', header=None)  # 没有表头

# 🌟 跳过行和指定列
df = pd.read_excel('data.xlsx', skiprows=2, usecols='A:C')  # 跳过前2行,只读A-C列
df = pd.read_excel('data.xlsx', usecols=[0, 2, 4])          # 按位置选择列

# 🌟 指定数据类型
df = pd.read_excel('data.xlsx', dtype={'工号': str, '年龄': int})

1.3.2 写入 Excel(to_excel)

python 复制代码
# 🌟 基础写入
df.to_excel('output.xlsx', index=False)

# 🌟 写入指定 Sheet
df.to_excel('output.xlsx', sheet_name='员工数据', index=False)

# 🌟 多个 DataFrame 写入不同 Sheet
with pd.ExcelWriter('output.xlsx') as writer:
    df_employees.to_excel(writer, sheet_name='员工', index=False)
    df_sales.to_excel(writer, sheet_name='销售', index=False)
    df_products.to_excel(writer, sheet_name='产品', index=False)

# 🌟 追加到已有 Excel 文件(需要 openpyxl)
with pd.ExcelWriter('output.xlsx', mode='a', engine='openpyxl') as writer:
    df_new.to_excel(writer, sheet_name='新数据', index=False)

1.3.3 Excel 引擎选择

引擎 读取 写入 特点
openpyxl 支持 .xlsx,功能最全
xlrd 只支持 .xls(旧格式)
xlsxwriter 写入功能强大,支持格式
python 复制代码
# 指定引擎
df = pd.read_excel('data.xlsx', engine='openpyxl')
df.to_excel('output.xlsx', engine='xlsxwriter')

1.4 JSON 文件操作

1.4.1 读取 JSON(read_json)

JSON 是 Web API 最常用的数据格式。

python 复制代码
# 🌟 从文件读取
df = pd.read_json('data.json')

# 🌟 从字符串读取
json_str = '''
[
    {"姓名": "张三", "年龄": 25},
    {"姓名": "李四", "年龄": 30}
]
'''
df = pd.read_json(json_str)

# 🌟 从 API 获取(配合 requests)
import requests
response = requests.get('https://api.example.com/data')
df = pd.read_json(response.text)

# 🌟 指定 orient(JSON 结构)
# orient='records': [{"col1": "a", "col2": "b"}, ...]  最常用
df = pd.read_json('data.json', orient='records')
# orient='index': {"row1": {"col1": "a", ...}, ...}
df = pd.read_json('data.json', orient='index')
# orient='columns': {"col1": {"row1": "a", ...}, ...}
df = pd.read_json('data.json', orient='columns')

1.4.2 写入 JSON(to_json)

python 复制代码
# 🌟 基础写入
df.to_json('output.json')

# 🌟 指定 orient
df.to_json('output.json', orient='records', force_ascii=False)  # force_ascii=False 保证中文正常显示

# 🌟 写入 JSON 字符串
json_str = df.to_json(orient='records', force_ascii=False)
print(json_str)
# [{"姓名":"张三","年龄":25}, {"姓名":"李四","年龄":30}]

1.5 SQL 数据库操作

1.5.1 连接数据库

python 复制代码
from sqlalchemy import create_engine

# 🌟 MySQL
engine = create_engine('mysql+pymysql://用户名:密码@主机:端口/数据库名')

# 🌟 PostgreSQL
engine = create_engine('postgresql://用户名:密码@主机:端口/数据库名')

# 🌟 SQLite(本地文件数据库)
engine = create_engine('sqlite:///mydatabase.db')

# 🌟 SQL Server
engine = create_engine('mssql+pyodbc://用户名:密码@DSN名')

1.5.2 读取 SQL(read_sql)

python 复制代码
# 🌟 读取整个表
df = pd.read_sql('SELECT * FROM employees', engine)

# 🌟 读取指定 SQL
df = pd.read_sql('''
    SELECT 姓名, 部门, 月薪 
    FROM employees 
    WHERE 月薪 > 20000
    ORDER BY 月薪 DESC
''', engine)

# 🌟 使用参数化查询(防止 SQL 注入)
df = pd.read_sql(
    'SELECT * FROM employees WHERE 部门 = %s',
    engine,
    params=('技术',)
)

# 🌟 分块读取大数据
df_iter = pd.read_sql('SELECT * FROM big_table', engine, chunksize=10000)
for chunk in df_iter:
    print(f"处理 {len(chunk)} 行")

1.5.3 写入 SQL(to_sql)

python 复制代码
# 🌟 基础写入(如果表存在会报错)
df.to_sql('employees', engine, index=False)

# 🌟 如果表存在,替换
df.to_sql('employees', engine, index=False, if_exists='replace')

# 🌟 如果表存在,追加
df.to_sql('employees', engine, index=False, if_exists='append')

# 🌟 指定数据类型
df.to_sql(
    'employees',
    engine,
    index=False,
    dtype={
        '姓名': sqlalchemy.types.VARCHAR(50),
        '年龄': sqlalchemy.types.INTEGER(),
        '月薪': sqlalchemy.types.DECIMAL(10, 2)
    }
)

1.6 其他常用格式

1.6.1 Parquet 格式(大数据推荐)

python 复制代码
# 🌟 读取 Parquet
df = pd.read_parquet('data.parquet')

# 🌟 写入 Parquet
df.to_parquet('output.parquet', index=False)

# 🌟 压缩(节省空间)
df.to_parquet('output.parquet', compression='gzip')

💡 Parquet 优势:列式存储,压缩率高,读写速度快,大数据生态标准格式。

1.6.2 HDF5 格式

python 复制代码
# 🌟 读取 HDF5
df = pd.read_hdf('data.h5', key='df')

# 🌟 写入 HDF5
df.to_hdf('output.h5', key='df', mode='w')

# 🌟 追加到 HDF5
df.to_hdf('output.h5', key='df', mode='a')

1.6.3 剪贴板操作

python 复制代码
# 🌟 从剪贴板读取(从 Excel 复制后直接读取)
df = pd.read_clipboard()

# 🌟 写入剪贴板(粘贴到 Excel)
df.to_clipboard(index=False)

1.6.4 格式对比

格式 优点 缺点 适用场景
CSV 通用、可读 慢、占空间、无类型 小数据、交换
Excel 人人会用 慢、大小限制 报告、人工编辑
JSON Web 标准 占空间 API、Web
Parquet 快、压缩、有类型 不可读 大数据存储
HDF5 快、可追加 依赖多 科学计算
SQL 可查询、事务 需要数据库 企业应用

1.7 实战案例:数据导入导出全流程

场景

你需要从多个数据源整合数据,处理后生成报告。

python 复制代码
import pandas as pd
from sqlalchemy import create_engine

# 1. 从 CSV 读取销售数据
sales_df = pd.read_csv('sales_2024.csv', encoding='utf-8', parse_dates=['日期'])
print(f"销售数据:{len(sales_df)} 行")

# 2. 从 Excel 读取产品信息
product_df = pd.read_excel('products.xlsx', sheet_name='产品清单')
print(f"产品数据:{len(product_df)} 行")

# 3. 从数据库读取客户信息
engine = create_engine('sqlite:///crm.db')
customer_df = pd.read_sql('SELECT * FROM customers', engine)
print(f"客户数据:{len(customer_df)} 行")

# 4. 数据合并(后续章节详细讲解)
merged_df = sales_df.merge(product_df, on='产品ID').merge(customer_df, on='客户ID')

# 5. 数据处理
merged_df['销售额'] = merged_df['数量'] * merged_df['单价']
merged_df['月份'] = merged_df['日期'].dt.to_period('M')

# 6. 生成月度汇总报告
monthly_report = merged_df.groupby('月份').agg({
    '销售额': 'sum',
    '数量': 'sum',
    '订单ID': 'count'
}).rename(columns={'订单ID': '订单数'})

# 7. 保存到多个格式
# 保存到 Excel(多个 Sheet)
with pd.ExcelWriter('月度报告.xlsx') as writer:
    monthly_report.to_excel(writer, sheet_name='月度汇总')
    merged_df.to_excel(writer, sheet_name='详细数据', index=False)

# 保存到 CSV
monthly_report.to_csv('月度报告.csv', encoding='utf-8-sig')

# 保存到 Parquet(用于后续分析)
merged_df.to_parquet('销售数据.parquet', index=False)

# 保存到数据库
monthly_report.to_sql('monthly_report', engine, if_exists='replace')

print("✅ 报告生成完成!")

1.8 本章小结

核心要点

CSVread_csv() / to_csv() ------ 最通用,注意编码和分隔符

Excelread_excel() / to_excel() ------ 需要 openpyxl,注意 Sheet 选择

JSONread_json() / to_json() ------ Web 数据标准,注意 orient

SQLread_sql() / to_sql() ------ 需要 SQLAlchemy,注意连接字符串

Parquetread_parquet() / to_parquet() ------ 大数据推荐格式

最佳实践

  • 读取时指定 encoding='utf-8'
  • 写入时设置 index=False
  • 大文件使用 chunksize 分块读取
  • 日期列使用 parse_dates 自动解析
相关推荐
李昊哲小课12 天前
PyArrow 完整教程
大数据·数据分析·pandas·pyarrow
云和数据.ChenGuang13 天前
T5大模型
人工智能·机器人·pandas·数据预处理·数据训练
MATLAB代码顾问14 天前
Python Pandas数据分析入门指南
python·数据分析·pandas
themingyi16 天前
Abaqus2024安装python包pandas
开发语言·python·pandas
一晌小贪欢16 天前
第26节:自动化办公——利用 Python 自动生成动态分析报告 (PPT/PDF)
开发语言·python·数据分析·自动化·powerpoint·pandas·数据可视化
留白_16 天前
pandas练习题
python·数据分析·pandas
留白_16 天前
pandas进阶学习
学习·pandas
abcy07121317 天前
python pandas csv异步后台清洗前端优先返回成功信息
前端·python·pandas
留白_18 天前
pandas文件读取与存储
开发语言·python·pandas
SilentSamsara18 天前
特征工程系统方法论:编码、分箱、交互特征与特征选择
开发语言·人工智能·python·机器学习·青少年编程·信息可视化·pandas