第四章:数据读取与保存
📋 章节概述
本章讲解 Pandas 的数据读写功能,涵盖 CSV、Excel、JSON、SQL 等常见数据格式。通过本章学习,你将掌握实际工作中最常用的数据导入导出技能。
🎯 学习目标
- 掌握 CSV 文件的读写操作
- 掌握 Excel 文件的读写操作
- 掌握 JSON 数据的读写操作
- 了解 SQL 数据库的读写操作
- 学会处理不同编码和分隔符
- 掌握大数据文件的分块读取
📊 知识结构图
数据读写
CSV
Excel
JSON
SQL
其他格式
read_csv
to_csv
编码处理
分块读取
read_excel
to_excel
多工作表
ExcelWriter
read_json
to_json
orient参数
嵌套JSON
read_sql
to_sql
SQLAlchemy
SQLite示例
Parquet
HDF5
Pickle
HTML
python
import pandas as pd
import numpy as np
import json
import os
# 设置显示选项
pd.set_option('display.max_columns', None)
pd.set_option('display.width', None)
# 创建工作目录
data_dir = "data"
os.makedirs(data_dir, exist_ok=True)
4.1 CSV 文件读写详解
CSV(Comma-Separated Values)是最常见的数据交换格式,几乎所有数据处理软件都支持 CSV 格式。
CSV 读写流程
read_csv
to_csv
CSV文件
DataFrame
常用参数
| 参数 | 说明 | 示例 |
|---|---|---|
sep |
分隔符 | sep=';' |
encoding |
编码格式 | encoding='utf-8' |
header |
指定行作为列名 | header=0 |
index_col |
指定某列为索引 | index_col='id' |
usecols |
只读取指定列 | usecols=['A','B'] |
nrows |
只读取前n行 | nrows=100 |
skiprows |
跳过指定行 | skiprows=2 |
示例1:创建示例数据并保存为 CSV
python
# 创建销售订单数据
orders_data = pd.DataFrame({
"订单号": ["ORD2026001", "ORD2026002", "ORD2026003", "ORD2026004", "ORD2026005",
"ORD2026006", "ORD2026007", "ORD2026008", "ORD2026009", "ORD2026010"],
"客户姓名": ["张伟", "李娜", "王强", "刘洋", "陈静", "赵敏", "周杰", "吴刚", "郑华", "孙丽"],
"产品名称": ["笔记本电脑", "无线鼠标", "机械键盘", "显示器", "耳机",
"平板电脑", "U盘", "移动硬盘", "摄像头", "音箱"],
"类别": ["电子产品", "配件", "配件", "电子产品", "配件",
"电子产品", "存储", "存储", "配件", "配件"],
"数量": [1, 2, 1, 2, 1, 1, 3, 1, 2, 1],
"单价": [5999, 99, 299, 1299, 199, 3499, 89, 459, 299, 159],
"订单日期": pd.to_datetime(["2026-01-15", "2026-01-16", "2026-01-18", "2026-01-20", "2026-01-22",
"2026-02-01", "2026-02-05", "2026-02-10", "2026-02-15", "2026-02-20"]),
"地区": ["北京", "上海", "广州", "深圳", "北京", "上海", "广州", "深圳", "北京", "上海"]
})
# 计算订单金额
orders_data["订单金额"] = orders_data["数量"] * orders_data["单价"]
print("销售订单数据预览:")
orders_data.head()
销售订单数据预览:
| | 订单号 | 客户姓名 | 产品名称 | 类别 | 数量 | 单价 | 订单日期 | 地区 | 订单金额 |
| 0 | ORD2026001 | 张伟 | 笔记本电脑 | 电子产品 | 1 | 5999 | 2026-01-15 | 北京 | 5999 |
| 1 | ORD2026002 | 李娜 | 无线鼠标 | 配件 | 2 | 99 | 2026-01-16 | 上海 | 198 |
| 2 | ORD2026003 | 王强 | 机械键盘 | 配件 | 1 | 299 | 2026-01-18 | 广州 | 299 |
| 3 | ORD2026004 | 刘洋 | 显示器 | 电子产品 | 2 | 1299 | 2026-01-20 | 深圳 | 2598 |
| 4 | ORD2026005 | 陈静 | 耳机 | 配件 | 1 | 199 | 2026-01-22 | 北京 | 199 |
|---|
python
# 保存为 CSV 文件
csv_path = f"{data_dir}/orders.csv"
orders_data.to_csv(csv_path, index=False, encoding='utf-8-sig') # utf-8-sig 兼容 Excel
print(f"数据已保存到: {csv_path}")
print(f"文件大小: {os.path.getsize(csv_path)} bytes")
数据已保存到: data/orders.csv
文件大小: 763 bytes
示例2:读取 CSV 文件
python
# 基本读取
print("基本读取:")
df_csv = pd.read_csv(csv_path)
df_csv.head(3)
基本读取:
| | 订单号 | 客户姓名 | 产品名称 | 类别 | 数量 | 单价 | 订单日期 | 地区 | 订单金额 |
| 0 | ORD2026001 | 张伟 | 笔记本电脑 | 电子产品 | 1 | 5999 | 2026-01-15 | 北京 | 5999 |
| 1 | ORD2026002 | 李娜 | 无线鼠标 | 配件 | 2 | 99 | 2026-01-16 | 上海 | 198 |
| 2 | ORD2026003 | 王强 | 机械键盘 | 配件 | 1 | 299 | 2026-01-18 | 广州 | 299 |
|---|
python
# 指定编码读取(处理中文)
print("指定编码读取:")
df_csv_utf8 = pd.read_csv(csv_path, encoding='utf-8-sig')
print(f"成功读取 {len(df_csv_utf8)} 行数据")
指定编码读取:
成功读取 10 行数据
python
# 指定某列为索引
print("指定某列为索引:")
df_indexed = pd.read_csv(csv_path, index_col='订单号')
df_indexed.head(3)
指定某列为索引:
| | 客户姓名 | 产品名称 | 类别 | 数量 | 单价 | 订单日期 | 地区 | 订单金额 |
| 订单号 | | | | | | | | |
| ORD2026001 | 张伟 | 笔记本电脑 | 电子产品 | 1 | 5999 | 2026-01-15 | 北京 | 5999 |
| ORD2026002 | 李娜 | 无线鼠标 | 配件 | 2 | 99 | 2026-01-16 | 上海 | 198 |
| ORD2026003 | 王强 | 机械键盘 | 配件 | 1 | 299 | 2026-01-18 | 广州 | 299 |
|---|
python
# 只读取指定列
print("只读取指定列:")
df_subset = pd.read_csv(csv_path, usecols=['客户姓名', '产品名称', '订单金额'])
df_subset.head()
只读取指定列:
| | 客户姓名 | 产品名称 | 订单金额 |
| 0 | 张伟 | 笔记本电脑 | 5999 |
| 1 | 李娜 | 无线鼠标 | 198 |
| 2 | 王强 | 机械键盘 | 299 |
| 3 | 刘洋 | 显示器 | 2598 |
| 4 | 陈静 | 耳机 | 199 |
|---|
python
# 读取前 N 行
print("读取前 N 行:")
df_partial = pd.read_csv(csv_path, nrows=5)
print(f"只读取前 5 行: {len(df_partial)} 行")
df_partial
读取前 N 行:
只读取前 5 行: 5 行
| | 订单号 | 客户姓名 | 产品名称 | 类别 | 数量 | 单价 | 订单日期 | 地区 | 订单金额 |
| 0 | ORD2026001 | 张伟 | 笔记本电脑 | 电子产品 | 1 | 5999 | 2026-01-15 | 北京 | 5999 |
| 1 | ORD2026002 | 李娜 | 无线鼠标 | 配件 | 2 | 99 | 2026-01-16 | 上海 | 198 |
| 2 | ORD2026003 | 王强 | 机械键盘 | 配件 | 1 | 299 | 2026-01-18 | 广州 | 299 |
| 3 | ORD2026004 | 刘洋 | 显示器 | 电子产品 | 2 | 1299 | 2026-01-20 | 深圳 | 2598 |
| 4 | ORD2026005 | 陈静 | 耳机 | 配件 | 1 | 199 | 2026-01-22 | 北京 | 199 |
|---|
示例3:处理不同分隔符
python
# 创建分号分隔的文件
semicolon_path = f"{data_dir}/orders_semicolon.csv"
orders_data.to_csv(semicolon_path, index=False, sep=';', encoding='utf-8-sig')
# 读取分号分隔的 CSV
print("读取分号分隔的 CSV:")
df_semicolon = pd.read_csv(semicolon_path, sep=';')
df_semicolon.head(3)
读取分号分隔的 CSV:
| | 订单号 | 客户姓名 | 产品名称 | 类别 | 数量 | 单价 | 订单日期 | 地区 | 订单金额 |
| 0 | ORD2026001 | 张伟 | 笔记本电脑 | 电子产品 | 1 | 5999 | 2026-01-15 | 北京 | 5999 |
| 1 | ORD2026002 | 李娜 | 无线鼠标 | 配件 | 2 | 99 | 2026-01-16 | 上海 | 198 |
| 2 | ORD2026003 | 王强 | 机械键盘 | 配件 | 1 | 299 | 2026-01-18 | 广州 | 299 |
|---|
示例4:大文件分块读取
当处理大文件时,可以使用 chunksize 参数分块读取,避免内存溢出。
python
# 创建一个大文件用于演示
large_data = pd.concat([orders_data] * 100, ignore_index=True) # 1000行
large_path = f"{data_dir}/large_orders.csv"
large_data.to_csv(large_path, index=False, encoding='utf-8-sig')
# 分块读取大文件
print("分块读取大文件:")
chunk_size = 200
chunks = []
for chunk in pd.read_csv(large_path, chunksize=chunk_size):
chunks.append(chunk)
print(f" 读取 chunk: {len(chunk)} 行")
df_large = pd.concat(chunks, ignore_index=True)
print(f"\n总计读取: {len(df_large)} 行")
分块读取大文件:
读取 chunk: 200 行
读取 chunk: 200 行
读取 chunk: 200 行
读取 chunk: 200 行
读取 chunk: 200 行
总计读取: 1000 行
4.2 Excel 文件读写详解
Excel 是办公场景中最常用的数据格式,Pandas 支持读写 Excel 文件。
依赖库
| 库 | 用途 |
|---|---|
openpyxl |
读写 .xlsx 格式(Excel 2007+) |
xlrd |
读取 .xls 格式(旧版 Excel) |
xlwt |
写入 .xls 格式(旧版 Excel) |
安装:pip install openpyxl xlrd xlwt
Excel 读写流程
read_excel
to_excel
ExcelWriter
Excel文件
DataFrame
多工作表
示例5:保存到 Excel
python
excel_path = f"{data_dir}/sales_report.xlsx"
# 保存到 Excel(单工作表)
print("保存到 Excel(单工作表):")
orders_data.to_excel(excel_path, index=False, sheet_name='订单数据')
print(f"已保存到: {excel_path}")
保存到 Excel(单工作表):
已保存到: data/sales_report.xlsx
python
# 保存多个工作表
print("保存多个工作表:")
with pd.ExcelWriter(excel_path, engine='openpyxl') as writer:
orders_data.to_excel(writer, sheet_name='订单数据', index=False)
# 创建汇总数据
summary = orders_data.groupby('类别').agg({
'订单金额': 'sum',
'数量': 'sum'
}).reset_index()
summary.to_excel(writer, sheet_name='类别汇总', index=False)
# 创建地区汇总
region_summary = orders_data.groupby('地区')['订单金额'].sum().reset_index()
region_summary.to_excel(writer, sheet_name='地区汇总', index=False)
print(f"已保存多个工作表到: {excel_path}")
保存多个工作表:
已保存多个工作表到: data/sales_report.xlsx
示例6:读取 Excel 文件
python
# 读取指定工作表
print("读取指定工作表:")
df_excel = pd.read_excel(excel_path, sheet_name='订单数据')
df_excel.head(3)
读取指定工作表:
| | 订单号 | 客户姓名 | 产品名称 | 类别 | 数量 | 单价 | 订单日期 | 地区 | 订单金额 |
| 0 | ORD2026001 | 张伟 | 笔记本电脑 | 电子产品 | 1 | 5999 | 2026-01-15 | 北京 | 5999 |
| 1 | ORD2026002 | 李娜 | 无线鼠标 | 配件 | 2 | 99 | 2026-01-16 | 上海 | 198 |
| 2 | ORD2026003 | 王强 | 机械键盘 | 配件 | 1 | 299 | 2026-01-18 | 广州 | 299 |
|---|
python
# 读取所有工作表
print("读取所有工作表:")
all_sheets = pd.read_excel(excel_path, sheet_name=None) # 返回字典
print(f"工作表列表: {list(all_sheets.keys())}")
for sheet_name, df in all_sheets.items():
print(f" {sheet_name}: {len(df)} 行")
读取所有工作表:
工作表列表: ['订单数据', '类别汇总', '地区汇总']
订单数据: 10 行
类别汇总: 3 行
地区汇总: 4 行
python
# 读取类别汇总
print("读取类别汇总:")
df_summary = pd.read_excel(excel_path, sheet_name='类别汇总')
df_summary
读取类别汇总:
| | 类别 | 订单金额 | 数量 |
| 0 | 存储 | 726 | 4 |
| 1 | 电子产品 | 12096 | 4 |
| 2 | 配件 | 1453 | 7 |
|---|
4.3 JSON 数据读写详解
JSON(JavaScript Object Notation)是 Web 开发中最常用的数据格式,常用于 API 数据传输和配置文件。
orient 参数说明
| 值 | 格式 | 示例 |
|---|---|---|
records |
记录列表 | [{}, {}, ...] |
index |
索引为键 | {'0': {}, '1': {}} |
columns |
列为键 | {'col': {'0': val}} |
values |
纯值数组 | [[], [], ...] |
read_json
to_json
JSON文件
DataFrame
records
index
columns
示例7:保存为 JSON
python
json_path = f"{data_dir}/orders.json"
# 保存为 JSON(records 格式)
print("保存为 JSON(records 格式):")
orders_data.to_json(json_path, orient='records', force_ascii=False, indent=2, date_format='iso')
print(f"已保存到: {json_path}")
# 显示 JSON 内容
with open(json_path, 'r', encoding='utf-8') as f:
json_content = json.load(f)
print(f"JSON 记录数: {len(json_content)}")
print(f"第一条记录: {json_content[0]}")
保存为 JSON(records 格式):
已保存到: data/orders.json
JSON 记录数: 10
第一条记录: {'订单号': 'ORD2026001', '客户姓名': '张伟', '产品名称': '笔记本电脑', '类别': '电子产品', '数量': 1, '单价': 5999, '订单日期': '2026-01-15T00:00:00.000', '地区': '北京', '订单金额': 5999}
python
# 不同 orient 格式对比
print("不同 orient 格式对比:")
for orient in ['records', 'index', 'columns', 'values']:
temp_path = f"{data_dir}/orders_{orient}.json"
orders_data.head(2).to_json(temp_path, orient=orient, force_ascii=False, date_format='iso')
with open(temp_path, 'r', encoding='utf-8') as f:
content = json.load(f)
print(f"\n orient='{orient}':")
print(f" {json.dumps(content, ensure_ascii=False)[:100]}...")
不同 orient 格式对比:
orient='records':
[{"订单号": "ORD2026001", "客户姓名": "张伟", "产品名称": "笔记本电脑", "类别": "电子产品", "数量": 1, "单价": 5999, "订单日期": "20...
orient='index':
{"0": {"订单号": "ORD2026001", "客户姓名": "张伟", "产品名称": "笔记本电脑", "类别": "电子产品", "数量": 1, "单价": 5999, "订单日期"...
orient='columns':
{"订单号": {"0": "ORD2026001", "1": "ORD2026002"}, "客户姓名": {"0": "张伟", "1": "李娜"}, "产品名称": {"0": "笔记本电脑...
orient='values':
[["ORD2026001", "张伟", "笔记本电脑", "电子产品", 1, 5999, "2026-01-15T00:00:00.000", "北京", 5999], ["ORD2026002...
示例8:读取 JSON
python
# 读取 JSON 文件
print("读取 JSON 文件:")
df_json = pd.read_json(json_path, orient='records')
df_json.head(3)
读取 JSON 文件:
| | 订单号 | 客户姓名 | 产品名称 | 类别 | 数量 | 单价 | 订单日期 | 地区 | 订单金额 |
| 0 | ORD2026001 | 张伟 | 笔记本电脑 | 电子产品 | 1 | 5999 | 2026-01-15T00:00:00.000 | 北京 | 5999 |
| 1 | ORD2026002 | 李娜 | 无线鼠标 | 配件 | 2 | 99 | 2026-01-16T00:00:00.000 | 上海 | 198 |
| 2 | ORD2026003 | 王强 | 机械键盘 | 配件 | 1 | 299 | 2026-01-18T00:00:00.000 | 广州 | 299 |
|---|
python
# 创建嵌套 JSON 示例
nested_json = {
"company": "科技有限公司",
"year": 2026,
"employees": [
{"name": "张伟", "department": "技术部", "salary": 12000},
{"name": "李娜", "department": "销售部", "salary": 15000},
{"name": "王强", "department": "技术部", "salary": 18000}
]
}
nested_path = f"{data_dir}/company.json"
with open(nested_path, 'w', encoding='utf-8') as f:
json.dump(nested_json, f, ensure_ascii=False, indent=2)
# 读取嵌套 JSON
print("读取嵌套 JSON:")
with open(nested_path, 'r', encoding='utf-8') as f:
nested_data = json.load(f)
df_employees = pd.DataFrame(nested_data['employees'])
print(f" 公司: {nested_data['company']}")
print(f" 年份: {nested_data['year']}")
print(" 员工数据:")
df_employees
读取嵌套 JSON:
公司: 科技有限公司
年份: 2026
员工数据:
| | name | department | salary |
| 0 | 张伟 | 技术部 | 12000 |
| 1 | 李娜 | 销售部 | 15000 |
| 2 | 王强 | 技术部 | 18000 |
|---|
4.4 SQL 数据库读写
Pandas 支持通过 SQLAlchemy 连接各种数据库(MySQL、PostgreSQL、SQLite 等)。
依赖库
| 库 | 用途 |
|---|---|
sqlalchemy |
数据库连接引擎 |
pymysql |
MySQL 驱动 |
psycopg2 |
PostgreSQL 驱动 |
连接字符串示例
python
# SQLite
sqlite:///:memory: # 内存数据库
sqlite:///path/to/db.sqlite # 文件数据库
# MySQL
mysql+pymysql://user:password@localhost/dbname
# PostgreSQL
postgresql://user:password@localhost/dbname
to_sql
read_sql
DataFrame
SQL数据库
SQLAlchemy
示例9:SQLite 内存数据库演示
python
try:
from sqlalchemy import create_engine
# 创建内存数据库
engine = create_engine('sqlite:///:memory:')
# 写入数据
orders_data.to_sql('orders', engine, index=False, if_exists='replace')
print("数据已写入 SQLite 内存数据库")
# 读取全部数据
df_sqlite = pd.read_sql('SELECT * FROM orders', engine)
print(f"读取到 {len(df_sqlite)} 行数据")
# 条件查询
df_high_value = pd.read_sql(
'SELECT * FROM orders WHERE "订单金额" > 1000 ORDER BY "订单金额" DESC',
engine
)
print(f"高价值订单(>1000): {len(df_high_value)} 条")
print("前3条:")
df_high_value[['订单号', '产品名称', '订单金额']].head(3)
except ImportError:
print("请安装 sqlalchemy: pip install sqlalchemy")
数据已写入 SQLite 内存数据库
读取到 10 行数据
高价值订单(>1000): 3 条
前3条:
示例10:SQLite 本地数据库文件
python
try:
from sqlalchemy import create_engine
# 创建本地 SQLite 数据库文件
sqlite_path = f"{data_dir}/sales_database.sqlite"
engine_file = create_engine(f'sqlite:///{sqlite_path}')
# 写入多个表
orders_data.to_sql('orders', engine_file, index=False, if_exists='replace')
# 创建汇总表
category_summary = orders_data.groupby('类别').agg({
'订单金额': 'sum',
'数量': 'sum'
}).reset_index()
category_summary.to_sql('category_summary', engine_file, index=False, if_exists='replace')
print(f"数据库文件已创建: {sqlite_path}")
print(f"文件大小: {os.path.getsize(sqlite_path)} bytes")
# 从本地数据库读取
df_from_db = pd.read_sql('SELECT * FROM orders', engine_file)
print(f"\n从数据库读取 orders 表: {len(df_from_db)} 行")
# 查询汇总表
df_summary_db = pd.read_sql('SELECT * FROM category_summary', engine_file)
print("category_summary 表内容:")
print(df_summary_db)
except ImportError:
print("请安装 sqlalchemy: pip install sqlalchemy")
数据库文件已创建: data/sales_database.sqlite
文件大小: 12288 bytes
从数据库读取 orders 表: 10 行
category_summary 表内容:
类别 订单金额 数量
0 存储 726 4
1 电子产品 12096 4
2 配件 1453 7
python
# SQL 复杂查询示例
try:
print("\nSQL 复杂查询 - 按地区统计订单金额:")
region_query = '''
SELECT 地区, COUNT(*) as 订单数, SUM(订单金额) as 总金额, AVG(订单金额) as 平均金额
FROM orders
GROUP BY 地区
ORDER BY 总金额 DESC
'''
df_region_stats = pd.read_sql(region_query, engine_file)
df_region_stats
except NameError:
print("请先运行上面的代码块创建数据库")
SQL 复杂查询 - 按地区统计订单金额:
4.5 其他格式简介
| 格式 | 读取 | 写入 | 适用场景 |
|---|---|---|---|
| Parquet | read_parquet() |
to_parquet() |
大数据处理 |
| HDF5 | read_hdf() |
to_hdf() |
科学数据 |
| Pickle | read_pickle() |
to_pickle() |
临时存储 |
| HTML | read_html() |
to_html() |
网页表格 |
| Clipboard | read_clipboard() |
to_clipboard() |
剪贴板 |
4.6 实战案例:销售数据整合
场景描述
你需要整合来自不同来源的销售数据:
- 从 CSV 文件导入线上订单数据
- 从 Excel 文件导入线下门店数据
- 从 JSON API 获取合作伙伴数据
- 合并所有数据并生成汇总报表
- 导出为多种格式供不同部门使用
CSV线上数据
数据合并
Excel线下数据
JSON合作数据
数据分析
Excel报表
CSV报表
JSON报表
步骤1:准备多来源数据
python
# 线上订单数据(CSV 格式)
online_data = pd.DataFrame({
"订单ID": [f"ON{str(i).zfill(5)}" for i in range(1, 6)],
"客户": ["客户A", "客户B", "客户C", "客户D", "客户E"],
"产品": ["产品X", "产品Y", "产品Z", "产品X", "产品Y"],
"金额": [1500, 2300, 1800, 2100, 1200],
"渠道": ["线上", "线上", "线上", "线上", "线上"],
"日期": pd.date_range("2026-01-01", periods=5)
})
# 线下门店数据(Excel 格式)
offline_data = pd.DataFrame({
"订单ID": [f"OFF{str(i).zfill(5)}" for i in range(1, 6)],
"客户": ["客户F", "客户G", "客户H", "客户I", "客户J"],
"产品": ["产品Y", "产品Z", "产品X", "产品Z", "产品Y"],
"金额": [2800, 1500, 3200, 1900, 2600],
"渠道": ["线下", "线下", "线下", "线下", "线下"],
"日期": pd.date_range("2026-01-01", periods=5)
})
# 合作伙伴数据(JSON 格式)
partner_json = {
"orders": [
{"订单ID": "PT00001", "客户": "客户K", "产品": "产品X", "金额": 3500, "渠道": "合作", "日期": "2026-01-03"},
{"订单ID": "PT00002", "客户": "客户L", "产品": "产品Y", "金额": 4200, "渠道": "合作", "日期": "2026-01-05"},
{"订单ID": "PT00003", "客户": "客户M", "产品": "产品Z", "金额": 2800, "渠道": "合作", "日期": "2026-01-07"}
]
}
partner_data = pd.DataFrame(partner_json["orders"])
partner_data["日期"] = pd.to_datetime(partner_data["日期"], format="%Y-%m-%d")
print("线上订单数据:")
print(online_data)
print("\n线下门店数据:")
print(offline_data)
print("\n合作伙伴数据:")
print(partner_data)
线上订单数据:
订单ID 客户 产品 金额 渠道 日期
0 ON00001 客户A 产品X 1500 线上 2026-01-01
1 ON00002 客户B 产品Y 2300 线上 2026-01-02
2 ON00003 客户C 产品Z 1800 线上 2026-01-03
3 ON00004 客户D 产品X 2100 线上 2026-01-04
4 ON00005 客户E 产品Y 1200 线上 2026-01-05
线下门店数据:
订单ID 客户 产品 金额 渠道 日期
0 OFF00001 客户F 产品Y 2800 线下 2026-01-01
1 OFF00002 客户G 产品Z 1500 线下 2026-01-02
2 OFF00003 客户H 产品X 3200 线下 2026-01-03
3 OFF00004 客户I 产品Z 1900 线下 2026-01-04
4 OFF00005 客户J 产品Y 2600 线下 2026-01-05
合作伙伴数据:
订单ID 客户 产品 金额 渠道 日期
0 PT00001 客户K 产品X 3500 合作 2026-01-03
1 PT00002 客户L 产品Y 4200 合作 2026-01-05
2 PT00003 客户M 产品Z 2800 合作 2026-01-07
步骤2:保存各来源数据到不同格式
python
online_path = f"{data_dir}/online_orders.csv"
offline_path = f"{data_dir}/offline_orders.xlsx"
partner_path = f"{data_dir}/partner_orders.json"
online_data.to_csv(online_path, index=False, encoding='utf-8-sig')
offline_data.to_excel(offline_path, index=False, sheet_name='线下订单')
partner_data.to_json(partner_path, orient='records', force_ascii=False, indent=2, date_format='iso')
print(f"线上数据已保存: {online_path}")
print(f"线下数据已保存: {offline_path}")
print(f"合作数据已保存: {partner_path}")
线上数据已保存: data/online_orders.csv
线下数据已保存: data/offline_orders.xlsx
合作数据已保存: data/partner_orders.json
步骤3:读取并合并所有数据
python
df_online = pd.read_csv(online_path)
df_offline = pd.read_excel(offline_path)
df_partner = pd.read_json(partner_path, orient='records')
df_partner["日期"] = pd.to_datetime(df_partner["日期"])
# 合并所有数据
all_orders = pd.concat([df_online, df_offline, df_partner], ignore_index=True)
print(f"线上订单: {len(df_online)} 条")
print(f"线下订单: {len(df_offline)} 条")
print(f"合作订单: {len(df_partner)} 条")
print(f"合并后总计: {len(all_orders)} 条")
print("\n合并后数据预览:")
all_orders
线上订单: 5 条
线下订单: 5 条
合作订单: 3 条
合并后总计: 13 条
合并后数据预览:
| | 订单ID | 客户 | 产品 | 金额 | 渠道 | 日期 |
| 0 | ON00001 | 客户A | 产品X | 1500 | 线上 | 2026-01-01 |
| 1 | ON00002 | 客户B | 产品Y | 2300 | 线上 | 2026-01-02 |
| 2 | ON00003 | 客户C | 产品Z | 1800 | 线上 | 2026-01-03 |
| 3 | ON00004 | 客户D | 产品X | 2100 | 线上 | 2026-01-04 |
| 4 | ON00005 | 客户E | 产品Y | 1200 | 线上 | 2026-01-05 |
| 5 | OFF00001 | 客户F | 产品Y | 2800 | 线下 | 2026-01-01 00:00:00 |
| 6 | OFF00002 | 客户G | 产品Z | 1500 | 线下 | 2026-01-02 00:00:00 |
| 7 | OFF00003 | 客户H | 产品X | 3200 | 线下 | 2026-01-03 00:00:00 |
| 8 | OFF00004 | 客户I | 产品Z | 1900 | 线下 | 2026-01-04 00:00:00 |
| 9 | OFF00005 | 客户J | 产品Y | 2600 | 线下 | 2026-01-05 00:00:00 |
| 10 | PT00001 | 客户K | 产品X | 3500 | 合作 | 2026-01-03 00:00:00 |
| 11 | PT00002 | 客户L | 产品Y | 4200 | 合作 | 2026-01-05 00:00:00 |
| 12 | PT00003 | 客户M | 产品Z | 2800 | 合作 | 2026-01-07 00:00:00 |
|---|
步骤4:数据分析
python
print("按渠道统计:")
channel_stats = all_orders.groupby("渠道").agg({
"金额": ["sum", "mean", "count"]
}).round(2)
channel_stats.columns = ["总金额", "平均金额", "订单数"]
channel_stats
按渠道统计:
| | 总金额 | 平均金额 | 订单数 |
| 渠道 | | | |
| 合作 | 10500 | 3500.0 | 3 |
| 线上 | 8900 | 1780.0 | 5 |
| 线下 | 12000 | 2400.0 | 5 |
|---|
python
print("按产品统计:")
product_stats = all_orders.groupby("产品")["金额"].sum().sort_values(ascending=False)
product_stats
按产品统计:
产品
产品Y 13100
产品X 10300
产品Z 8000
Name: 金额, dtype: int64
步骤5:导出汇总报表(多格式)
python
report_path = f"{data_dir}/sales_report_final"
# 导出为 Excel(多工作表)
excel_report_path = f"{report_path}.xlsx"
with pd.ExcelWriter(excel_report_path, engine='openpyxl') as writer:
all_orders.to_excel(writer, sheet_name='全部订单', index=False)
channel_stats.to_excel(writer, sheet_name='渠道统计')
product_stats.to_excel(writer, sheet_name='产品统计')
print(f"Excel 报表: {excel_report_path}")
# 导出为 CSV
csv_report_path = f"{report_path}.csv"
all_orders.to_csv(csv_report_path, index=False, encoding='utf-8-sig')
print(f"CSV 报表: {csv_report_path}")
# 导出为 JSON
json_report_path = f"{report_path}.json"
all_orders.to_json(json_report_path, orient='records', force_ascii=False, indent=2, date_format='iso')
print(f"JSON 报表: {json_report_path}")
Excel 报表: data/sales_report_final.xlsx
CSV 报表: data/sales_report_final.csv
JSON 报表: data/sales_report_final.json
本章小结
学习内容回顾
1. CSV 文件读写
read_csv(): 读取 CSV,支持多种参数to_csv(): 保存为 CSV- 处理编码、分隔符、大文件分块读取
2. Excel 文件读写
read_excel(): 读取 Excel,支持多工作表to_excel(): 保存为 ExcelExcelWriter: 多工作表写入- 依赖: openpyxl, xlrd
3. JSON 数据读写
read_json(): 读取 JSONto_json(): 保存为 JSONorient参数: records, index, columns, values
4. SQL 数据库读写
read_sql(): 执行 SQL 查询to_sql(): 写入数据库表- SQLAlchemy: 数据库连接引擎
5. 其他格式
- Parquet: 高效列式存储
- HDF5: 层次化数据格式
- Pickle: Python 对象序列化
6. 实战应用
- 多来源数据整合
- 数据格式转换
- 报表生成与导出
下章预告
第五章:数据选择与过滤
将学习数据选择与过滤的核心技能,包括:
- loc 基于标签的选择
- iloc 基于位置的选择
- 布尔索引条件筛选
- query() 方法查询
- isin()、between() 等便捷方法
课后练习
练习1:创建一个包含学生成绩的数据集,然后:
- 保存为 CSV 文件(使用不同编码)
- 保存为 Excel 文件(多工作表)
- 保存为 JSON 文件(不同 orient)
练习2:从 CSV 文件读取数据,然后:
- 只读取前 10 行
- 只读取指定列
- 跳过前 2 行
练习3:创建一个 SQLite 数据库,然后:
- 将 DataFrame 写入数据库
- 使用 SQL 查询筛选数据
- 将查询结果读取为 DataFrame
练习4:整合多个数据文件:
- 创建 3 个 CSV 文件(模拟不同月份数据)
- 读取并合并所有数据
- 按月份统计并导出报表