专题:Python 自动化办公系统学习
关键词:Python, 自动化办公, pandas, Excel, 数据分析, read_excel, to_excel, DataFrame, 数据清洗, Python
一、pandas与Excel概述
pandas是Python数据分析领域的核心库,它提供了高性能、易用的数据结构和数据分析工具。当pandas遇到Excel时,数据分析的效率和灵活性将得到质的飞跃。在日常办公中,Excel是最广泛使用的数据处理工具,但面对大量数据、重复操作或复杂分析需求时,纯手工操作往往效率低下且容易出错。pandas的出现彻底改变了这一局面,它让Excel数据分析完全自动化成为现实。
pandas操作Excel依赖于底层引擎。目前主流的选择有三个:openpyxl是功能最全面的引擎,支持.xlsx格式的读写,并且可以操作Excel样式、图表、条件格式等;xlrd用于读取旧的.xls格式文件,自2.0版本起仅支持.xls格式;xlwt用于写入.xls格式文件。在大多数现代办公场景中,建议优先使用openpyxl引擎,它对新版Excel格式支持最完善,功能覆盖面最广。
安装配置非常简单,只需通过pip安装pandas和相关引擎即可。推荐使用Anaconda发行版,它已经预装了pandas和openpyxl。如果使用标准Python环境,可以通过以下命令安装。需要注意的是,不同引擎之间可能存在功能差异,在读取旧版.xls文件时需要额外安装xlrd;而需要写入带样式或图表的Excel文件时,则必须安装openpyxl。在实际项目中,建议统一使用.xlsx格式以避免引擎兼容性问题。
# 安装pandas及相关Excel引擎
pip install pandas openpyxl xlrd xlwt
# 验证安装
import pandas as pd
print(pd.__version__) # 查看pandas版本
print(pd.io.excel.__version__) # 查看Excel支持版本
引擎选择建议:处理.xlsx文件首选openpyxl;处理旧版.xls文件使用xlrd读取、xlwt写入。pandas 1.2.0版本以后,默认可选引擎为openpyxl。当文件较大时,可指定engine='openpyxl'以获得更稳定的性能表现。建议在项目中统一文件格式为.xlsx,可大幅减少引擎相关的兼容性问题。
pandas整合Excel的适用场景非常广泛。在财务领域,可以自动汇总月度报表、生成对账文件;在销售领域,可以批量处理订单数据、计算业绩指标;在人力资源领域,可以自动整合员工信息、计算薪酬数据;在数据分析领域,可以快速完成数据清洗、聚合分析和可视化输出。无论哪个行业,只要涉及Excel数据的批量处理和自动化分析,pandas都能提供高效的解决方案。学习曲线虽然存在,但一旦掌握核心API,便能以极低的代码量完成原本需要数小时的手工操作。
# 检查可用引擎
import pandas as pd
# 列出pandas支持的Excel引擎
engines = ['openpyxl', 'xlrd', 'xlwt', 'pyxlsb', 'odf']
for eng in engines:
try:
__import__(eng)
print(f"{eng}: 可用")
except ImportError:
print(f"{eng}: 未安装")
二、读取Excel文件
pandas读取Excel文件的核心函数是pd.read_excel(),它功能强大、参数丰富,能够应对各种复杂的读取场景。最基本的用法只需传入文件路径即可,但在实际工作中,我们往往需要精细控制读取过程。read_excel的关键参数包括:sheet_name指定要读取的工作表名称或索引;header指定表头行号;index_col指定索引列;dtype指定列数据类型;parse_dates自动解析日期列;usecols限定读取的列范围;skiprows跳过指定行数。
多Sheet读取是Excel数据处理中的高频需求。许多业务报表将不同月份的数据放在不同Sheet中,或者将汇总数据和明细数据分布在多个Sheet里。pandas提供了灵活的读取方式:可以指定单个Sheet名称读取,也可以传入Sheet名称列表批量读取,还可以通过sheet_name=None一次性读取所有Sheet,返回一个以Sheet名为键的字典。这种方式在处理结构相似的多个Sheet时尤为高效,可以配合循环语句统一处理。
# 基础读取:读取第一个Sheet
import pandas as pd
df = pd.read_excel('销售数据.xlsx')
print(df.head())
# 精细控制读取参数
df = pd.read_excel(
'销售数据.xlsx',
sheet_name='1月', # 指定工作表
header=0, # 第一行为列名
index_col='订单号', # 设置索引列
dtype={'客户ID': str}, # 指定列数据类型
parse_dates=['下单日期'], # 解析日期列
usecols='A:F' # 只读A到F列
)
print(df.info())
# 读取所有Sheet并合并处理
import pandas as pd
import os
# 获取所有Sheet名称
xls = pd.ExcelFile('月度销售报告.xlsx')
sheet_names = xls.sheet_names
print(f"共 {len(sheet_names)} 个Sheet: {sheet_names}")
# 读取所有Sheet到一个字典
all_sheets = pd.read_excel('月度销售报告.xlsx', sheet_name=None)
# 合并所有Sheet的数据
combined_df = pd.DataFrame()
for sheet_name, df in all_sheets.items():
df['月份'] = sheet_name # 添加月份标记
combined_df = pd.concat([combined_df, df], ignore_index=True)
print(f"合并后数据量: {combined_df.shape}")
print(combined_df.head())
处理大文件时,性能优化尤为重要。对于超过10万行的Excel文件,如果一次性全部读入内存可能会导致内存溢出或读取速度极慢。pandas提供了多种优化策略:一是使用chunksize参数进行分块读取,每次只处理指定行数的数据;二是使用usecols仅读取需要的列,避免加载无用数据;三是配合dtype参数指定列类型,尤其是将包含混合类型数据的列统一为字符串,可以避免类型推断带来的额外开销。此外,对于GB级别的超大型数据,建议先将Excel转换为CSV格式后再用pandas处理,或者直接使用Dask等分布式计算框架。
# 大文件分块读取
import pandas as pd
# 使用chunksize分块读取,每次处理5000行
chunks = pd.read_excel(
'超大销售数据.xlsx',
sheet_name='Sheet1',
chunksize=5000,
dtype={'订单号': str, '客户ID': str}
)
# 逐块处理
result_parts = []
for i, chunk in enumerate(chunks):
# 对每个块进行处理
chunk['处理批次'] = i + 1
chunk['销售额'] = chunk['数量'] * chunk['单价']
result_parts.append(chunk)
# 合并所有块
final_df = pd.concat(result_parts, ignore_index=True)
print(f"总行数: {len(final_df)}")
print(f"总销售额: {final_df['销售额'].sum():,.2f}")
性能优化核心原则:①只读取需要的列(usecols)和行(skiprows/nrows);②为文本列指定dtype=str,避免类型推断开销;③超大文件使用chunksize分块处理;④若只需读取特定行列范围,先通过openpyxl等底层引擎定位再读取。遵循这些原则,即使是包含百万行数据的Excel文件也能高效处理。
三、写入Excel文件
pandas写入Excel的核心函数是df.to_excel(),它将DataFrame直接写入Excel文件。基础用法仅需指定文件名和Sheet名称,但实际业务中往往需要更精细的控制。to_excel的重要参数包括:sheet_name指定工作表名称;index控制是否写入行索引;header控制是否写入列名;columns指定要写入的列及顺序;startrow和startcol控制写入起始位置,实现自由定位写入。
多Sheet写入是构建复合报表的必备技能。通过pd.ExcelWriter上下文管理器,可以在一个Excel文件中写入多个工作表。这在生成月度报告、部门汇总等场景中极为实用——可以将不同维度的分析结果放在不同Sheet中,形成层次分明的工作簿。ExcelWriter还支持mode='a'追加模式,可以在不破坏现有Sheet的情况下向已存在的Excel文件写入新的Sheet。
# 单Sheet写入
import pandas as pd
# 创建示例数据
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'部门': ['销售部', '技术部', '销售部', '技术部'],
'销售额': [85000, 72000, 95000, 68000],
'提成': [8500, 3600, 9500, 3400]
}
df = pd.DataFrame(data)
# 写入Excel,不包含索引
df.to_excel('员工业绩.xlsx', sheet_name='业绩汇总', index=False)
print("文件已生成:员工业绩.xlsx")
# 多Sheet写入(使用ExcelWriter)
import pandas as pd
# 准备多个数据表
summary_df = pd.DataFrame({'月份': ['1月','2月','3月'], '总销售额': [100,120,150]})
detail_df = pd.DataFrame({'产品': ['A','B','C'], '销量': [30,45,25]})
analysis_df = pd.DataFrame({'指标': ['均值','中位数','标准差'], '值': [45,42,8.5]})
# 使用ExcelWriter写入多个Sheet
with pd.ExcelWriter('多Sheet报表.xlsx', engine='openpyxl') as writer:
summary_df.to_excel(writer, sheet_name='汇总', index=False)
detail_df.to_excel(writer, sheet_name='明细', index=False)
analysis_df.to_excel(writer, sheet_name='分析', index=False)
print("多Sheet报表已生成!")
# 追加模式:向已有文件添加新Sheet
new_df = pd.DataFrame({'备注': ['已完成'], '日期': ['2025-01-15']})
with pd.ExcelWriter('多Sheet报表.xlsx', engine='openpyxl', mode='a') as writer:
new_df.to_excel(writer, sheet_name='备注', index=False)
print("已追加Sheet:备注")
自由定位写入是一个非常实用的功能。在实际业务中,我们经常需要在Excel的特定位置写入数据,而不是每次都从A1单元格开始。例如,在已有的报表模板中填充数据,或者在同一Sheet的不同区域写入多张表格。pandas通过startrow和startcol参数支持这种精确控制。更高级的用法还可以结合openpyxl的load_workbook功能,先加载现有Excel文件,然后利用pandas在其指定位置写入数据,实现模板化报表生成。
# 自由定位写入
import pandas as pd
# 准备数据
df1 = pd.DataFrame({'产品': ['A','B'], '销量': [100,200]})
df2 = pd.DataFrame({'城市': ['北京','上海'], '销售额': [500,600]})
# 在同一Sheet的不同位置写入
with pd.ExcelWriter('自由定位示例.xlsx', engine='openpyxl') as writer:
# 从A1开始写入第一个表格
df1.to_excel(writer, sheet_name='数据', startrow=0, startcol=0, index=False)
# 从第5行开始写入第二个表格
df2.to_excel(writer, sheet_name='数据', startrow=5, startcol=0, index=False)
# 在已有模板中填充数据
from openpyxl import load_workbook
# 先创建模板文件或加载已有模板
template_path = '报表模板.xlsx'
try:
book = load_workbook(template_path)
except FileNotFoundError:
# 创建简单模板
from openpyxl import Workbook
book = Workbook()
ws = book.active
ws['A1'] = '月度销售报表'
ws['A3'] = '产品'
ws['B3'] = '销量'
ws['C3'] = '金额'
book.save(template_path)
# 在模板的第4行开始填充数据
with pd.ExcelWriter(template_path, engine='openpyxl', mode='a', if_sheet_exists='overlay') as writer:
data = {'产品': ['X','Y','Z'], '销量': [50,60,70], '金额': [5000,7200,9100]}
pd.DataFrame(data).to_excel(
writer, sheet_name='Sheet', startrow=3, startcol=0, index=False, header=False
)
print("模板化报表生成成功!")
写入策略总结:①单表写入直接用to_excel即可;②多Sheet写入务必使用ExcelWriter上下文管理器,确保文件正确关闭;③追加写入需指定mode='a',配合if_sheet_exists参数处理同名Sheet覆盖策略;④自由定位使用startrow/startcol实现精确控制;⑤模板化报表可结合openpyxl的load_workbook与pandas的ExcelWriter一起使用。
四、数据类型处理
Excel数据类型处理的复杂性往往超出预期。一个看似简单的Excel文件,在读取后可能暴露出各种各样的数据类型问题:日期列被读成字符串、数值列中包含文本符号导致整列为对象类型、百分数显示为小数、身份证号因科学计数法丢失精度等等。掌握pandas的数据类型处理技巧,是确保Excel数据分析准确性的基础。pandas中的核心数据类型包括:int64(整数)、float64(浮点数)、object(文本/混合类型)、datetime64(日期时间)、timedelta(时间差)、category(分类数据)和bool(布尔类型)。
日期时间类型处理是Excel数据清洗中最常见的需求之一。Excel中的日期存储方式与Python存在差异——Excel将日期存储为自1900年1月1日以来的序列号,而pandas使用datetime64类型。read_excel的parse_dates参数可以自动解析常见的日期格式,但对于不规范的日期字符串(如"2025.01.15"、"2025年1月15日"、"01/15/25"等),可能需要手动指定格式进行转换。此外,跨时区的日期数据处理、日期范围生成、日期特征提取(年、月、周、季度等)也都是实际业务中的高频操作。
# 日期类型处理
import pandas as pd
# 读取时自动解析日期
df = pd.read_excel('销售数据.xlsx', parse_dates=['下单日期', '发货日期'])
print(df.dtypes)
# 处理不规范的日期格式
df = pd.read_excel('日期数据.xlsx')
df['不规范日期'] = pd.to_datetime(
df['日期字符串'],
format='%Y年%m月%d日',
errors='coerce' # 无法解析的设为NaT
)
print(df[['日期字符串', '不规范日期']].head())
# 日期特征提取
df['年份'] = df['下单日期'].dt.year
df['月份'] = df['下单日期'].dt.month
df['周数'] = df['下单日期'].dt.isocalendar().week
df['季度'] = df['下单日期'].dt.quarter
df['是否周末'] = df['下单日期'].dt.dayofweek >= 5
print(df[['下单日期', '年份', '月份', '季度', '是否周末']].head())
# 数值类型与文本类型处理
import pandas as pd
import numpy as np
# 读取时指定列类型
df = pd.read_excel(
'客户数据.xlsx',
dtype={
'客户ID': str, # 防止长数字精度丢失
'手机号': str, # 手机号作为文本处理
'邮编': str # 邮编作为文本处理
}
)
# 数值列中的特殊字符处理
df['金额(元)'] = df['金额字符串'].str.replace('¥', '', regex=False)
df['金额(元)'] = df['金额(元)'].str.replace(',', '', regex=False)
df['金额(元)'] = pd.to_numeric(df['金额(元)'], errors='coerce')
# 百分数字符串转数值
df['增长率'] = df['增长率%'].str.replace('%', '', regex=False)
df['增长率'] = pd.to_numeric(df['增长率'], errors='coerce') / 100
print(df.dtypes)
print(df[['金额字符串', '金额(元)', '增长率%', '增长率']].head())
缺失值处理是数据分析中绕不开的环节。Excel数据中常见的缺失表现形式包括:空单元格、"N/A"、"NULL"、"None"、"未知"等。pandas在读取Excel时默认会将空单元格识别为NaN,但文本类型的缺失标记则需要手动处理。通过na_values参数,可以指定哪些值应被视为缺失值。在读取完成后,还需要根据业务需求决定缺失值的处理策略:是直接删除(dropna)、用固定值填充(fillna)、用均值/中位数填充,还是用前向/后向填充(method='ffill'/'bfill')。不同的处理策略适用于不同的业务场景,需要根据数据特点灵活选择。
# 缺失值处理完整示例
import pandas as pd
import numpy as np
# 读取时指定缺失值标记
df = pd.read_excel(
'不完整数据.xlsx',
na_values=['N/A', 'NULL', 'None', '未知', ''],
keep_default_na=True
)
# 分析缺失情况
print("各列缺失数量:")
print(df.isnull().sum())
print(f"\n缺失率:\n{df.isnull().mean() * 100:.1f}%")
# 根据列类型采用不同填充策略
# 数值列:用中位数填充
df['年龄'].fillna(df['年龄'].median(), inplace=True)
# 金额列:用均值填充
df['收入'].fillna(df['收入'].mean(), inplace=True)
# 文本列:用"未知"填充
df['部门'].fillna('未知', inplace=True)
# 时间序列:用前向填充
df['最近登录日期'].fillna(method='ffill', inplace=True)
print("\n处理后的缺失情况:")
print(df.isnull().sum())
类型处理黄金法则:①身份证号、手机号、银行卡号等长数字列必须在读取时指定dtype=str,否则会丢失精度;②日期列优先在read_excel时用parse_dates处理,效率最高;③包含混合类型的列统一转为字符串后再按需清洗;④缺失值处理策略需结合业务场景选择,数值列推荐用中位数(抗异常值),类别列用众数或"未知"标记,时间序列用前向填充。
五、数据清洗自动化
数据清洗是数据分析中耗时最长的环节,往往占据整个分析流程60%以上的时间。pandas提供了强大的数据清洗工具,可以将原本需要手动逐行检查的繁琐工作自动化。常见的数据清洗任务包括:重复值处理、缺失值处理、异常值检测、数据标准化和列名规范化等。将这些清洗步骤封装为可复用的函数,是构建自动化数据处理流水线的关键。
重复值处理是数据清洗的第一步。Excel中可能因为数据合并、人工录入错误等原因产生重复记录。pandas的duplicated()方法可以检测重复行,drop_duplicates()方法可以删除重复行。实际业务中,判断"重复"的标准往往不是整行完全相同,而是基于特定列(如订单号、身份证号)来判断。此外,保留哪一条重复记录也是一个需要根据业务逻辑确定的决策——通常是保留第一条、最后一条或根据时间戳保留最新的一条。
# 重复值处理
import pandas as pd
df = pd.read_excel('订单数据.xlsx')
print(f"原始数据量: {len(df)}")
# 查找完全重复的行
duplicates = df[df.duplicated()]
print(f"完全重复行数: {len(duplicates)}")
# 基于特定列去重
# 保留每个订单ID的第一条记录
df_clean = df.drop_duplicates(subset=['订单ID'], keep='first')
print(f"去重后数据量: {len(df_clean)}")
# 基于多列组合去重(保留最后一条)
df_clean2 = df.drop_duplicates(subset=['客户ID', '产品ID', '下单日期'], keep='last')
# 标记重复行以便人工复核
df['是否重复'] = df.duplicated(subset=['订单ID'], keep=False)
repeat_records = df[df['是否重复'] == True].sort_values('订单ID')
print(f"需人工复核的重复记录数: {len(repeat_records)}")
# 异常值检测与处理(3σ原则和IQR方法)
import pandas as pd
import numpy as np
df = pd.read_excel('销售业绩.xlsx')
# 方法一:3σ原则检测异常值
def detect_outliers_3sigma(series):
mean = series.mean()
std = series.std()
lower = mean - 3 * std
upper = mean + 3 * std
return (series < lower) | (series > upper)
# 检测销售额列的异常值
outlier_mask = detect_outliers_3sigma(df['销售额'])
print(f"3σ方法检测到 {outlier_mask.sum()} 个异常值")
print(df[outlier_mask][['姓名', '销售额']])
# 方法二:IQR方法检测异常值
def detect_outliers_iqr(series):
Q1 = series.quantile(0.25)
Q3 = series.quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
return (series < lower) | (series > upper)
# 异常值处理:用上下限截尾
Q1 = df['销售额'].quantile(0.25)
Q3 = df['销售额'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
df['销售额_修正'] = df['销售额'].clip(lower=lower, upper=upper)
print(f"原始销售额: 均值={df['销售额'].mean():.0f}, 标准差={df['销售额'].std():.0f}")
print(f"修正后销售额: 均值={df['销售额_修正'].mean():.0f}, 标准差={df['销售额_修正'].std():.0f}")
数据标准化与列名规范化是提升数据质量的重要环节。不同来源的数据往往采用不同的命名规范和格式标准:同一个指标可能叫"销售额"也可能叫"销售金额"或"销售收入";日期格式可能是"2025-01-15"也可能是"2025/01/15";文本中可能混入多余空格或特殊字符。通过建立标准映射表和正则表达式,可以将这些不规范的字段名和格式统一为标准形式。列名规范化的最佳实践是统一使用小写字母+下划线命名法,并去除特殊字符,这样在后续编程处理时更加便捷。
# 数据标准化与列名规范化
import pandas as pd
import re
df = pd.read_excel('混乱数据.xlsx')
print("原始列名:", df.columns.tolist())
# 列名规范化函数
def normalize_column_name(name):
# 去除首尾空格和特殊字符
name = name.strip()
name = re.sub(r'[^一-龥a-zA-Z0-9_]', '_', name)
# 中文字段名保持不变,英文字段转为小写
if re.match(r'^[a-zA-Z]', name):
name = name.lower()
return name
df.columns = [normalize_column_name(col) for col in df.columns]
print("规范化后列名:", df.columns.tolist())
# 文本数据标准化
# 去除文本中的多余空格
df['客户姓名'] = df['客户姓名'].str.strip()
# 统一大小写
df['城市'] = df['城市'].str.title()
# 统一分类名称
dept_map = {
'销': '销售部', '销部': '销售部', '销售部': '销售部',
'技': '技术部', '技术部': '技术部', '技部': '技术部',
}
df['部门'] = df['部门'].map(dept_map).fillna(df['部门'])
print(df[['客户姓名', '城市', '部门']].head())
数据清洗流水线设计原则:①将每个清洗步骤封装为独立函数,方便测试和复用;②使用pandas的链式调用(pipe方法)串联多个清洗步骤,代码更简洁;③保留清洗前的原始数据快照,便于追溯和对比;④对清洗规则进行参数化配置,使清洗流程可以适应不同数据源。一个良好的数据清洗流水线应具备可配置、可追溯、可测试的特点。
六、数据聚合分析
数据聚合分析是pandas最强大的功能之一。Excel中的数据透视表虽然功能强大,但操作复杂、难以复用,且面对大数据量时容易卡顿。pandas的聚合分析能力完全覆盖了Excel透视表的功能,而且更加灵活、可编程、可复用。核心工具包括:groupby分组统计、pivot_table透视表、crosstab交叉表和agg聚合函数自定义。
groupby是pandas分组计算的核心方法,它采用"拆分-应用-合并"的模式。首先根据指定的列将数据拆分为多个组,然后对每个组应用聚合函数或转换函数,最后将结果合并为新的DataFrame。groupby支持各种聚合函数,包括sum、mean、count、min、max、std、var等内置函数,也支持通过agg方法自定义聚合逻辑。对于复杂的业务场景,还可以同时按多列分组、使用多个聚合函数、以及通过transform方法在每个组的上下文中进行数据转换。
# groupby分组统计详解
import pandas as pd
import numpy as np
df = pd.read_excel('销售数据.xlsx')
# 单列分组-基础聚合
dept_stats = df.groupby('部门')['销售额'].agg(['sum', 'mean', 'count', 'std'])
dept_stats.columns = ['总销售额', '平均销售额', '订单数', '标准差']
dept_stats = dept_stats.round(2).reset_index()
print("部门销售统计:")
print(dept_stats)
# 多列分组-多维度聚合
multi_stats = df.groupby(['区域', '产品类别']).agg(
总销售额=('销售额', 'sum'),
平均单价=('单价', 'mean'),
订单数量=('订单号', 'count'),
最大折扣=('折扣率', 'max')
).reset_index()
print("\n区域×产品类别统计:")
print(multi_stats.head())
# transform:在组内进行数据转换
df['部门销售额占比'] = df.groupby('部门')['销售额'].transform(
lambda x: x / x.sum() * 100
)
print("\n各部门内销售额占比:")
print(df[['姓名', '部门', '销售额', '部门销售额占比']].head())
# pivot_table透视表 - Excel透视表的Python版
import pandas as pd
df = pd.read_excel('销售数据.xlsx')
# 创建透视表
pivot = pd.pivot_table(
df,
values='销售额', # 要聚合的值
index='区域', # 行索引
columns='产品类别', # 列索引
aggfunc='sum', # 聚合函数
fill_value=0, # 缺失值填充
margins=True, # 显示合计行
margins_name='合计' # 合计行名称
)
print("销售透视表(区域×产品类别):")
print(pivot)
# 多级透视表
multi_pivot = pd.pivot_table(
df,
values=['销售额', '数量'],
index=['区域', '城市'],
columns='季度',
aggfunc={'销售额': 'sum', '数量': 'mean'},
fill_value=0
)
print("\n多维度透视表:")
print(multi_pivot.head())
# crosstab交叉表
cross = pd.crosstab(
index=df['区域'],
columns=df['产品类别'],
values=df['销售额'],
aggfunc='sum',
normalize='columns', # 按列归一化
margins=True
).round(4) * 100
print("\n销售交叉表(百分比):")
print(cross)
自定义聚合函数是应对复杂业务需求的利器。虽然sum、mean等内置聚合函数能满足大部分场景,但实际业务中往往需要更复杂的聚合逻辑。例如:计算每个月的累计销售额、统计每个客户的首单和末单时间、计算每个类别的销售排名等。通过agg方法可以传入自定义函数,或同时使用多个内置函数与自定义函数。此外,使用named aggregation语法可以让输出列名更加清晰,直接指定输出列名和对应的聚合逻辑,使得代码可读性大大增强。
# 自定义聚合与多级索引处理
import pandas as pd
import numpy as np
df = pd.read_excel('销售数据.xlsx')
# 自定义聚合函数
def range_func(x):
return x.max() - x.min()
def cv_func(x):
# 变异系数:衡量数据离散程度
return x.std() / x.mean() if x.mean() != 0 else 0
# 同时使用内置函数和自定义函数
custom_stats = df.groupby('产品类别').agg(
总销量=('数量', 'sum'),
平均价格=('单价', 'mean'),
价格差异=('单价', range_func),
价格变异系数=('单价', cv_func),
客户覆盖数=('客户ID', 'nunique')
).reset_index()
print("自定义聚合统计:")
print(custom_stats)
# 多级索引展平处理
multi_level = df.groupby(['区域', '产品类别']).agg(
销售额=('销售额', 'sum'),
订单数=('订单号', 'count')
)
print(f"\n多级索引类型: {type(multi_level.index)}")
print(multi_level.head())
# 展平多级索引
flat_df = multi_level.reset_index()
print("\n展平后:")
print(flat_df.head())
# 多级索引排序
sorted_df = multi_level.sort_index(level='区域', ascending=True)
print("\n按区域排序后:")
print(sorted_df.head())
聚合分析最佳实践:①groupby适合多维度分组统计,推荐与agg配合使用named aggregation语法,输出列名更清晰;②pivot_table直接对标Excel透视表,适合行列交叉汇总,加上margins=True可以自动生成合计行列;③crosstab适合频次和占比分析,normalize参数可灵活控制归一化方向;④复杂的业务聚合逻辑通过自定义函数实现,建议将函数定义在groupby之前,保持代码逻辑清晰。
七、多表关联与合并
在实际工作中,数据往往分散在多个Excel文件中。销售数据在一个文件,客户信息在另一个文件,产品目录又在第三个文件中。要完成完整的分析,必须将这些分散的数据关联起来。pandas提供了三种核心的表关联工具:merge(类似SQL的JOIN操作)、join(基于索引的关联)、concat(纵向或横向拼接)。掌握这三种工具,就可以取代Excel中VLOOKUP函数的所有功能,并且更加高效和灵活。
merge是pandas中最强大的表关联方法,它的工作原理类似于SQL中的JOIN。通过指定how参数可以控制关联方式:inner(内连接,仅保留匹配的行)、left(左连接,保留左表所有行)、right(右连接,保留右表所有行)、outer(外连接,保留两表所有行)。通过on参数指定关联键,当两表关联键列名不同时,可以使用left_on和right_on分别指定。merge完全可以取代Excel中的VLOOKUP函数,而且功能更强大、性能更好、使用更灵活。
# merge表关联 - VLOOKUP的完美替代
import pandas as pd
# 加载三个关联表
orders = pd.read_excel('订单表.xlsx')
customers = pd.read_excel('客户表.xlsx')
products = pd.read_excel('产品表.xlsx')
print(f"订单表: {orders.shape}")
print(f"客户表: {customers.shape}")
print(f"产品表: {products.shape}")
# 左连接:订单关联客户信息(等价于Excel VLOOKUP)
df = orders.merge(customers, on='客户ID', how='left')
print(f"\n关联客户后: {df.shape}")
print(df.head())
# 多表链式关联
df_full = orders.merge(customers, on='客户ID', how='left') \
.merge(products, on='产品ID', how='left')
print(f"\n完整关联后: {df_full.shape}")
print(df_full.columns.tolist())
# 不同键名的关联
sales = pd.read_excel('销售表.xlsx') # 列名: '客户编号'
result = sales.merge(
customers,
left_on='客户编号',
right_on='客户ID',
how='left'
)
print("\n不同键名关联:")
print(result[['客户编号', '客户名称', '销售额']].head())
# join与concat - 索引关联与拼接
import pandas as pd
# join:基于索引关联
sales_by_dept = pd.DataFrame({
'总销售额': [150000, 120000, 90000]
}, index=['销售部', '技术部', '市场部'])
headcount = pd.DataFrame({
'人数': [20, 35, 12],
'平均工龄': [3.5, 2.8, 4.1]
}, index=['销售部', '技术部', '市场部'])
# 基于索引自动关联
combined = sales_by_dept.join(headcount)
combined['人均产出'] = combined['总销售额'] / combined['人数']
print("基于索引关联:")
print(combined)
# concat纵向拼接:合并多个结构相同的表
jan = pd.read_excel('1月销售.xlsx')
feb = pd.read_excel('2月销售.xlsx')
mar = pd.read_excel('3月销售.xlsx')
# 纵向拼接所有月份数据
all_months = pd.concat(
[jan, feb, mar],
ignore_index=True,
keys=['1月', '2月', '3月']
)
print(f"\n纵向拼接后: {all_months.shape}")
print(all_months.head())
# 横向拼接:拼接不同维度的数据
scores = pd.DataFrame({'姓名': ['张三','李四'], '语文': [90,85], '数学': [95,88]})
extras = pd.DataFrame({'姓名': ['张三','李四'], '英语': [92,80], '物理': [88,90]})
horizontal = pd.merge(scores, extras, on='姓名')
print("\n横向拼接:")
print(horizontal)
多表关联计算是构建自动化报表的核心技术。在实际业务中,除了简单的字段关联外,往往还需要进行关联后的计算。例如:将订单表与产品表关联后计算折扣金额;将销售表与目标表关联后计算完成率;将多个部门的预算表和实际支出表关联后计算差异分析。这些操作在Excel中需要手动使用VLOOKUP + 公式组合完成,而在pandas中只需一次merge操作配合列计算即可自动化完成。如果数据量巨大(超过10万行),pandas的merge性能也远优于Excel的VLOOKUP。
# 多表关联计算实战
import pandas as pd
# 加载数据
sales = pd.read_excel('销售明细.xlsx')
targets = pd.read_excel('销售目标.xlsx')
costs = pd.read_excel('产品成本.xlsx')
# 多表关联 + 计算新字段
report = sales.merge(targets, on=['区域', '月份'], how='left') \
.merge(costs, on='产品ID', how='left')
# 计算各类指标
report['销售成本'] = report['数量'] * report['单位成本']
report['毛利'] = report['销售额'] - report['销售成本']
report['毛利率'] = (report['毛利'] / report['销售额'] * 100).round(2)
report['目标完成率'] = (report['销售额'] / report['目标额'] * 100).round(2)
report['达标状态'] = report['目标完成率'].apply(
lambda x: '超额完成' if x >= 100 else '未达标'
)
print("关联计算后的报表:")
print(report[['区域', '月份', '销售额', '目标额', '目标完成率', '达标状态', '毛利率']].head())
# 按区域汇总报表
summary = report.groupby('区域').agg(
总销售额=('销售额', 'sum'),
总目标=('目标额', 'sum'),
平均毛利率=('毛利率', 'mean'),
达标月数=('达标状态', lambda x: (x == '超额完成').sum())
).reset_index()
summary['完成率'] = (summary['总销售额'] / summary['总目标'] * 100).round(2)
print("\n区域汇总报表:")
print(summary)
表关联核心要点:①merge是VLOOKUP的最佳替代方案,可以一次性关联多个表,且支持所有JOIN类型;②关联前务必检查关联键的数据类型是否一致(例如,一个表的客户ID是int,另一个是str会导致关联失败);③大表关联时,先对关联键建立索引可以大幅提升性能;④concat纵向拼接时用ignore_index=True重置索引,用keys参数添加来源标记,便于追踪数据来源。
八、条件格式与样式输出
pandas导出的Excel文件默认是纯数据格式,没有任何样式。但在实际工作中,我们往往需要输出带有条件格式、颜色标记、表格样式等视觉元素的专业报表。虽然pandas本身不直接支持Excel样式操作,但可以通过集成openpyxl来实现丰富的样式控制。结合openpyxl,我们可以设置单元格字体、背景色、边框、对齐方式、列宽行高等,还可以添加数据条、色阶、图标集等条件格式。
使用openpyxl设置样式分为两步:第一步使用pandas的ExcelWriter将数据写入Excel文件,第二步使用openpyxl的load_workbook加载该文件并进行样式设置。这种模式的好处是既利用了pandas高效的数据处理能力,又利用了openpyxl丰富的样式控制功能。另一种更简洁的方式是直接使用openpyxl的Worksheet对象在写入过程中同步设置样式,但需要对openpyxl的API有较深入的了解。
# 使用openpyxl设置Excel样式
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import (
Font, PatternFill, Alignment,
Border, Side, numbers
)
from openpyxl.utils import get_column_letter
df = pd.read_excel('销售数据.xlsx')
# 第一步:用pandas写入数据
output_path = '样式化报表.xlsx'
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='销售报表', index=False)
# 第二步:用openpyxl添加样式
wb = load_workbook(output_path)
ws = wb['销售报表']
# 定义样式
header_font = Font(name='Microsoft YaHei', bold=True, color='FFFFFF', size=11)
header_fill = PatternFill(start_color='2E7D32', end_color='2E7D32', fill_type='solid')
header_alignment = Alignment(horizontal='center', vertical='center')
thin_border = Border(
left=Side(style='thin'),
right=Side(style='thin'),
top=Side(style='thin'),
bottom=Side(style='thin')
)
# 设置表头样式
for col in range(1, ws.max_column + 1):
cell = ws.cell(row=1, column=col)
cell.font = header_font
cell.fill = header_fill
cell.alignment = header_alignment
cell.border = thin_border
# 设置数据区域样式
for row in range(2, ws.max_row + 1):
for col in range(1, ws.max_column + 1):
cell = ws.cell(row=row, column=col)
cell.border = thin_border
cell.alignment = Alignment(horizontal='center', vertical='center')
# 自动调整列宽
for col in range(1, ws.max_column + 1):
max_length = 0
column_letter = get_column_letter(col)
for row in range(1, ws.max_row + 1):
cell_value = str(ws.cell(row=row, column=col).value or '')
max_length = max(max_length, len(cell_value.encode('utf-8')))
ws.column_dimensions[column_letter].width = min(max_length + 2, 30)
wb.save(output_path)
print("样式化报表已生成!")
# 条件格式:高亮、数据条、色阶
import pandas as pd
from openpyxl import load_workbook
from openpyxl.formatting.rule import CellIsRule, DataBarRule, ColorScaleRule
from openpyxl.styles import PatternFill, Font
df = pd.read_excel('销售业绩.xlsx')
output_path = '条件格式报表.xlsx'
# 写入数据
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='业绩分析', index=False)
# 添加条件格式
wb = load_workbook(output_path)
ws = wb['业绩分析']
# 1. 高亮规则:销售额大于90000的标绿
green_fill = PatternFill(start_color='C6EFCE', end_color='C6EFCE', fill_type='solid')
ws.conditional_formatting.add(
'C2:C1000',
CellIsRule(operator='greaterThan', formula=['90000'], fill=green_fill)
)
# 2. 高亮规则:销售额低于50000的标红
red_fill = PatternFill(start_color='FFC7CE', end_color='FFC7CE', fill_type='solid')
red_font = Font(color='9C0006')
ws.conditional_formatting.add(
'C2:C1000',
CellIsRule(operator='lessThan', formula=['50000'], fill=red_fill, font=red_font)
)
# 3. 数据条:在销售额列显示渐变数据条
data_bar = DataBarRule(
start_type='min',
end_type='max',
color='5B9BD5',
showValue=True
)
ws.conditional_formatting.add('C2:C1000', data_bar)
# 4. 色阶:在提成列使用三色色阶
ws.conditional_formatting.add(
'D2:D1000',
ColorScaleRule(
start_type='min', start_color='F8696B',
mid_type='percentile', mid_value=50, mid_color='FFEB84',
end_type='max', end_color='63BE7B'
)
)
# 设置列宽
ws.column_dimensions['A'].width = 12
ws.column_dimensions['B'].width = 10
ws.column_dimensions['C'].width = 15
ws.column_dimensions['D'].width = 12
wb.save(output_path)
print("带条件格式的报表已生成!")
print("- 绿色高亮: 销售额 > 90000")
print("- 红色高亮: 销售额 < 50000")
print("- 数据条: 销售额相对大小可视化")
print("- 色阶: 提成金额渐变显示")
除了基础样式和条件格式,专业的Excel报表还需要关注页面布局和打印设置。通过openpyxl可以设置打印区域、页眉页脚、重复标题行等高级功能。此外,还可以向Excel中添加图表、图片和超链接,甚至可以插入数据验证下拉列表和冻结窗格。这些高级功能使得pandas + openpyxl的组合不仅可以替代Excel的手工操作,还能生成比手动操作更加专业和一致的报表。对于需要定期生成的周报、月报等,可以将整个样式设置流程封装为函数,实现一键生成专业报表。
# 高级样式设置:冻结窗格、分组显示、格式化数字
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import numbers
from openpyxl.utils import get_column_letter
df = pd.read_excel('财务报表.xlsx')
output_path = '专业报表.xlsx'
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='财务报表', index=False)
wb = load_workbook(output_path)
ws = wb['财务报表']
# 冻结首行和首列
ws.freeze_panes = 'B2'
# 数字格式:金额列显示为货币格式
for row in range(2, ws.max_row + 1):
for col in [3, 4, 5]: # 假设3-5列为金额列
cell = ws.cell(row=row, column=col)
if cell.value is not None:
cell.number_format = '#,##0.00'
# 百分比格式
for row in range(2, ws.max_row + 1):
cell = ws.cell(row=row, column=6) # 假设第6列为百分比
if cell.value is not None:
cell.number_format = '0.00%'
# 设置打印区域
ws.print_area = f'A1:{get_column_letter(ws.max_column)}{ws.max_row}'
# 添加筛选器
ws.auto_filter.ref = f'A1:{get_column_letter(ws.max_column)}{ws.max_row}'
# 设置行高
ws.row_dimensions[1].height = 25
for row in range(2, ws.max_row + 1):
ws.row_dimensions[row].height = 20
wb.save(output_path)
print("专业级报表生成成功!")
print("- 冻结窗格: 首行+首列冻结")
print("- 数字格式: 金额千分位、百分比格式")
print("- 筛选器: 自动筛选已启用")
样式输出最佳实践:①先用pandas写入纯数据,再用openpyxl加载后设置样式,这是最灵活的模式;②将常用的样式定义(表头样式、边框样式、数字格式等)封装为配置字典或函数,方便复用;③条件格式中使用CellIsRule做值判断、DataBarRule做数据条、ColorScaleRule做色阶,三者可以组合使用;④对于周报月报等周期性报表,将整个"数据处理+样式设置"流程封装为一个函数,参数化配置,实现一键出报表。
九、实战案例
理论知识的价值最终要体现在解决实际问题上。本章通过三个完整的实战案例,展示如何将前面学习的pandas与Excel整合技巧应用到真实的业务场景中。每个案例都包含完整的数据处理流程:从原始Excel文件读取,到数据清洗和转换,再到聚合分析和样式输出,最后生成专业的Excel报表。这些案例可以直接作为模板,应用到类似的实际工作中。
案例一:销售数据月度汇总报表
某公司每天生成销售明细数据,需要每月自动生成一份汇总报表,包含按区域、产品类别、销售人员的多维度销售统计分析。手动制作这样一份报表需要2-3小时,而且容易出错。使用pandas可以将整个过程压缩到几秒钟,并且保证结果完全一致。本案例的完整流程包括:读取当月所有日期的销售明细文件、合并数据、进行多维度分组统计、生成透视表、最后输出为带样式的专业Excel报表。
# 销售数据月度汇总自动生成
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
import glob
import os
# 第一步:读取当月所有销售明细
file_pattern = 'data/销售明细_2025_01_*.xlsx'
all_files = glob.glob(file_pattern)
print(f"找到 {len(all_files)} 个销售明细文件")
dfs = []
for file in all_files:
df = pd.read_excel(file)
dfs.append(df)
sales_df = pd.concat(dfs, ignore_index=True)
print(f"合并后数据总量: {len(sales_df)} 行")
# 第二步:数据清洗
sales_df.drop_duplicates(subset=['订单号'], inplace=True)
sales_df.dropna(subset=['销售额'], inplace=True)
# 第三步:多维度汇总
# 3.1 按区域汇总
region_summary = sales_df.groupby('区域').agg(
销售额=('销售额', 'sum'),
订单数=('订单号', 'count'),
客户数=('客户ID', 'nunique')
).reset_index()
region_summary['客单价'] = (region_summary['销售额'] / region_summary['客户数']).round(2)
# 3.2 按产品类别汇总
product_summary = sales_df.groupby('产品类别').agg(
销售额=('销售额', 'sum'),
销量=('数量', 'sum'),
订单数=('订单号', 'count')
).reset_index()
# 3.3 生成透视表
pivot = pd.pivot_table(
sales_df,
values='销售额',
index='区域',
columns='产品类别',
aggfunc='sum',
fill_value=0,
margins=True,
margins_name='合计'
).reset_index()
# 第四步:写入Excel并设置样式
output_path = '月度销售汇总报表_2025年1月.xlsx'
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
region_summary.to_excel(writer, sheet_name='区域汇总', index=False)
product_summary.to_excel(writer, sheet_name='产品汇总', index=False)
pivot.to_excel(writer, sheet_name='透视分析', index=True)
# 应用样式
wb = load_workbook(output_path)
header_style = Font(bold=True, color='FFFFFF', size=11)
header_fill = PatternFill(start_color='2E7D32', end_color='2E7D32', fill_type='solid')
thin_border = Border(
left=Side(style='thin'), right=Side(style='thin'),
top=Side(style='thin'), bottom=Side(style='thin')
)
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
for col in range(1, ws.max_column + 1):
cell = ws.cell(row=1, column=col)
cell.font = header_style
cell.fill = header_fill
cell.border = thin_border
cell.alignment = Alignment(horizontal='center')
wb.save(output_path)
print(f"月度汇总报表已生成: {output_path}")
案例二:多部门数据合并分析
大型企业通常有多个业务部门,每个部门独立维护自己的业务数据。在进行公司级分析时,需要将各部门的数据合并起来。不同部门的数据结构可能存在差异:有的部门用"员工姓名",有的用"姓名";有的用"2025-01"表示月份,有的用"2025年1月"。本案例展示如何处理这种数据结构不一致的情况,完成多部门数据的统一合并与分析。
# 多部门数据合并分析
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
import os
# 各部门数据文件列表
dept_files = {
'销售部': 'data/销售部业绩.xlsx',
'技术部': 'data/技术部绩效.xlsx',
'市场部': 'data/市场部报告.xlsx'
}
# 定义各字段的标准映射
field_mapping = {
'员工姓名': '姓名', '姓名': '姓名', '员工': '姓名',
'销售额': '业绩', '业绩金额': '业绩', '业绩': '业绩',
'月份': '月份', '月': '月份', '统计月': '月份'
}
all_dept_data = []
for dept_name, file_path in dept_files.items():
df = pd.read_excel(file_path)
# 统一列名
df.rename(columns=field_mapping, inplace=True)
# 只保留标准列
standard_cols = [col for col in ['姓名', '业绩', '月份'] if col in df.columns]
df = df[standard_cols]
df['部门'] = dept_name
all_dept_data.append(df)
# 合并所有部门数据
combined = pd.concat(all_dept_data, ignore_index=True)
# 统一月份格式
combined['月份'] = combined['月份'].astype(str).str.replace('年', '-').str.replace('月', '')
# 多维度分析
# 部门维度汇总
dept_analysis = combined.groupby('部门').agg(
总业绩=('业绩', 'sum'),
平均业绩=('业绩', 'mean'),
人数=('姓名', 'nunique')
).reset_index()
dept_analysis['人均业绩'] = (dept_analysis['总业绩'] / dept_analysis['人数']).round(2)
# 部门+月份维度汇总
monthly_dept = combined.groupby(['月份', '部门'])['业绩'].sum().reset_index()
# 输出报表
output_path = '多部门合并分析报表.xlsx'
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
combined.to_excel(writer, sheet_name='合并数据', index=False)
dept_analysis.to_excel(writer, sheet_name='部门汇总', index=False)
monthly_dept.to_excel(writer, sheet_name='月度部门分析', index=False)
wb = load_workbook(output_path)
for ws in wb.worksheets:
ws.freeze_panes = 'A2'
wb.save(output_path)
print(f"多部门合并分析报表已生成: {output_path}")
# 打印关键发现
best_dept = dept_analysis.loc[dept_analysis['人均业绩'].idxmax()]
print(f"\n人均业绩最佳部门: {best_dept['部门']} ({best_dept['人均业绩']:.0f}元/人)")
案例三:财务报表自动化生成
财务报表是企业最核心的定期报告之一,对数据准确性、格式规范性要求极高。传统的手工制作方式不仅耗时,而且容易因公式错误、格式错乱等问题导致返工。使用pandas + openpyxl的自动化方案,可以将财务报表的生成时间从半天缩短到几分钟,同时消除人为错误。本案例展示如何从原始账目数据自动生成包含收入明细表、费用明细表、利润汇总表和关键指标仪表盘的完整财务报表。
# 财务报表自动化生成
import pandas as pd
import numpy as np
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side, numbers
from openpyxl.utils import get_column_letter
# 读取原始财务数据
income = pd.read_excel('财务数据/收入明细.xlsx')
expenses = pd.read_excel('财务数据/费用明细.xlsx')
print(f"收入数据: {income.shape}, 费用数据: {expenses.shape}")
# 数据清洗
income.dropna(subset=['金额'], inplace=True)
expenses.dropna(subset=['金额'], inplace=True)
# 计算核心指标
total_income = income['金额'].sum()
total_expenses = expenses['金额'].sum()
net_profit = total_income - total_expenses
profit_margin = (net_profit / total_income * 100) if total_income != 0 else 0
# 按类别汇总
income_by_cat = income.groupby('收入类别')['金额'].sum().reset_index()
income_by_cat['占比'] = (income_by_cat['金额'] / total_income * 100).round(2)
expense_by_cat = expenses.groupby('费用类别')['金额'].sum().reset_index()
expense_by_cat['占比'] = (expense_by_cat['金额'] / total_expenses * 100).round(2)
# 构建利润汇总表
profit_summary = pd.DataFrame({
'项目': ['总收入', '总费用', '净利润', '利润率'],
'金额': [total_income, total_expenses, net_profit, profit_margin],
'备注': ['', '', '', '净利润/总收入']
})
# 写入Excel
output_path = '财务报表_自动生成.xlsx'
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
profit_summary.to_excel(writer, sheet_name='利润汇总', index=False)
income_by_cat.to_excel(writer, sheet_name='收入分析', index=False)
expense_by_cat.to_excel(writer, sheet_name='费用分析', index=False)
# 专业样式配置
wb = load_workbook(output_path)
styles = {
'header_font': Font(name='Microsoft YaHei', bold=True, color='FFFFFF', size=11),
'header_fill': PatternFill(start_color='1B5E20', end_color='1B5E20', fill_type='solid'),
'title_font': Font(name='Microsoft YaHei', bold=True, size=14, color='1B5E20'),
'money_fmt': '#,##0.00',
'pct_fmt': '0.00"%"',
'thin_border': Border(
left=Side(style='thin'), right=Side(style='thin'),
top=Side(style='thin'), bottom=Side(style='thin')
)
}
for ws in wb.worksheets:
ws.freeze_panes = 'A2'
# 表头样式
for col in range(1, ws.max_column + 1):
cell = ws.cell(row=1, column=col)
cell.font = styles['header_font']
cell.fill = styles['header_fill']
cell.alignment = Alignment(horizontal='center')
cell.border = styles['thin_border']
# 利润汇总表特殊样式
ws_profit = wb['利润汇总']
for row in range(2, ws_profit.max_row + 1):
ws_profit.cell(row=row, column=1).font = Font(bold=True)
# 金额列格式
if row <= 3:
ws_profit.cell(row=row, column=2).number_format = styles['money_fmt']
else:
ws_profit.cell(row=row, column=2).number_format = '0.00'
# 加粗净利润行
for col in range(1, ws_profit.max_column + 1):
profit_row = 3 # 净利润在第3行(含表头)
ws_profit.cell(row=profit_row, column=col).font = Font(bold=True, color='1B5E20', size=12)
ws_profit.cell(row=profit_row, column=col).border = Border(
top=Side(style='double'), bottom=Side(style='double'),
left=Side(style='thin'), right=Side(style='thin')
)
wb.save(output_path)
print(f"财务报表已自动生成: {output_path}")
print(f"--- 财务摘要 ---")
print(f"总收入: {total_income:,.2f}")
print(f"总费用: {total_expenses:,.2f}")
print(f"净利润: {net_profit:,.2f}")
print(f"利润率: {profit_margin:.2f}%")
实战总结:三个案例覆盖了pandas+Excel整合最典型的应用场景。案例一(月度销售汇总)展示了多文件合并+多维度汇总的标准流程;案例二(多部门合并)展示了数据结构不一致时的清洗和统一策略;案例三(财务报表)展示了专业样式设置和关键指标计算。在实际工作中,可以将这些案例中的代码作为模板,根据具体业务需求进行修改和扩展,快速构建自己的Excel数据分析自动化流水线。