Pandas是Python数据分析的核心库,提供了强大的Excel表格处理能力。本文将详细介绍如何使用Pandas高效合并多个Excel文件,涵盖各种常见场景和进阶技巧。
一、基础合并方法
1. 合并相同结构的Excel文件
当多个Excel文件具有完全相同的列结构时,可以使用简单的纵向合并:
import pandas as pd
import glob
# 获取所有Excel文件
all_files = glob.glob("data/*.xlsx") # 支持.xls和.xlsx
# 读取并合并
df_list = []
for file in all_files:
df = pd.read_excel(file)
df_list.append(df)
combined_df = pd.concat(df_list, ignore_index=True)
# 保存合并结果
combined_df.to_excel("combined_data.xlsx", index=False)
2. 处理不同Sheet的合并
当数据分散在不同Sheet但结构相同时:
# 读取单个文件中的多个Sheet
file_path = "multi_sheet_data.xlsx"
sheets_dict = pd.read_excel(file_path, sheet_name=None)
# 合并所有Sheet
all_sheets = []
for sheet_name, df in sheets_dict.items():
df['source_sheet'] = sheet_name # 添加来源标记
all_sheets.append(df)
combined_sheets = pd.concat(all_sheets, ignore_index=True)
二、处理结构差异的表格
1. 列名不完全相同的情况
# 方法1:只保留共有列
common_columns = set()
for file in all_files:
df = pd.read_excel(file, nrows=0) # 只读取列名
common_columns.update(df.columns)
combined_df = pd.concat(
[pd.read_excel(file)[list(common_columns)] for file in all_files],
ignore_index=True
)
# 方法2:保留所有列,缺失值填充NA
combined_df = pd.concat(
[pd.read_excel(file) for file in all_files],
ignore_index=True,
sort=False # 避免列排序
)
2. 添加来源标识列
combined_data = pd.DataFrame()
for i, file in enumerate(all_files):
df = pd.read_excel(file)
df['source_file'] = file # 添加来源文件列
df['file_index'] = i # 添加文件序号
combined_data = pd.concat([combined_data, df], ignore_index=True)
三、高级合并技巧
1. 基于关键列的横向合并(类似SQL JOIN)
# 假设有两个需要关联的表格
df1 = pd.read_excel("orders.xlsx")
df2 = pd.read_excel("customers.xlsx")
# 内连接合并
merged_df = pd.merge(
df1,
df2,
on="customer_id", # 关联键
how="inner" # 连接方式:inner/left/right/outer
)
2. 大数据量分块处理
当处理大型Excel文件时,使用分块读取避免内存不足:
chunk_size = 10000 # 每次处理1万行
chunks = []
for file in all_files:
for chunk in pd.read_excel(file, chunksize=chunk_size):
chunks.append(chunk)
# 合并分块
combined_df = pd.concat(chunks, ignore_index=True)
3. 自定义合并逻辑
def custom_merge(df1, df2):
"""自定义合并逻辑示例"""
# 只合并df2中存在但df1中没有的客户
new_customers = df2[~df2['customer_id'].isin(df1['customer_id'])]
return pd.concat([df1, new_customers], ignore_index=True)
df1 = pd.read_excel("existing_customers.xlsx")
df2 = pd.read_excel("new_customers.xlsx")
result_df = custom_merge(df1, df2)
四、性能优化方案
1. 使用更高效的数据格式
# 先将Excel转为Parquet等高效格式
for file in all_files:
df = pd.read_excel(file)
df.to_parquet(file.replace(".xlsx", ".parquet"))
# 然后合并Parquet文件
parquet_files = glob.glob("data/*.parquet")
dfs = [pd.read_parquet(f) for f in parquet_files]
combined_df = pd.concat(dfs, ignore_index=True)
2. 多进程加速合并
from multiprocessing import Pool
def read_excel(file):
return pd.read_excel(file)
with Pool(processes=4) as pool: # 使用4个进程
df_list = pool.map(read_excel, all_files)
combined_df = pd.concat(df_list, ignore_index=True)
3. 内存优化技巧
# 指定数据类型减少内存占用
dtype_dict = {
'id': 'int32',
'price': 'float32',
'description': 'category'
}
df = pd.read_excel("large_file.xlsx", dtype=dtype_dict)
五、实战案例:销售数据整合
假设有以下需求:
- 合并2023年各月销售数据(每月一个Excel文件)
- 各月字段略有不同
- 需要计算总销售额并分析趋势
import pandas as pd
import glob
# 1. 读取并合并数据
sales_files = glob.glob("sales_2023_*.xlsx")
all_sales = []
for file in sales_files:
df = pd.read_excel(file)
# 统一列名
df.columns = df.columns.str.lower().str.replace(" ", "_")
# 确保必要列存在
if 'sales_amount' not in df.columns:
if 'amount' in df.columns:
df = df.rename(columns={'amount': 'sales_amount'})
else:
df['sales_amount'] = 0 # 默认值
df['month'] = file.split('_')[-1].replace('.xlsx', '')
all_sales.append(df)
# 合并数据
combined_sales = pd.concat(all_sales, ignore_index=True)
# 2. 数据清洗
combined_sales['sales_amount'] = pd.to_numeric(
combined_sales['sales_amount'],
errors='coerce'
).fillna(0)
# 3. 分析月销售额
monthly_sales = combined_sales.groupby('month')['sales_amount'].sum()
monthly_sales.plot(kind='bar', title='Monthly Sales 2023')
# 4. 保存结果
with pd.ExcelWriter('sales_report_2023.xlsx') as writer:
combined_sales.to_excel(writer, sheet_name='All Data', index=False)
monthly_sales.to_excel(writer, sheet_name='Monthly Summary')
六、常见问题解决方案
1. 处理编码问题
# 尝试不同编码
try:
df = pd.read_excel("data.xlsx")
except UnicodeDecodeError:
df = pd.read_excel("data.xlsx", encoding='gbk') # 中文常见编码
2. 跳过非数据行
# 跳过前3行非表头数据
df = pd.read_excel("file.xlsx", skiprows=3)
3. 处理合并时的重复数据
# 标记重复行
combined_df['is_duplicate'] = combined_df.duplicated()
# 或直接删除完全重复的行
combined_df = combined_df.drop_duplicates()
# 基于关键列去重
combined_df = combined_df.drop_duplicates(subset=['id', 'date'])
4. 处理Excel中的日期格式
# 读取时指定日期列
df = pd.read_excel("file.xlsx", parse_dates=['order_date'])
# 或读取后转换
df['order_date'] = pd.to_datetime(df['order_date'], errors='coerce')
七、最佳实践建议
- 文件检查:合并前先检查各文件结构,可使用
pd.read_excel(file, nrows=5)
预览 - 日志记录:记录合并过程中的文件读取情况
- 异常处理:捕获并处理可能的读取错误
- 内存监控:处理大文件时监控内存使用情况
- 版本兼容:注意
openpyxl
和xlrd
引擎的版本兼容性
通过本指南,您应该已经掌握了使用Pandas合并Excel文件的各种技术。根据您的具体需求选择合适的方法,简单的纵向合并使用pd.concat
,复杂的关联合并使用pd.merge
,大数据量场景考虑分块处理或格式转换。