1221 words
6 minutes
Python 数据处理技巧:pandas 实战笔记

处理了几百个 Excel 文件,从每天加班到半小时搞定。pandas 用好了真能救命。

先说说背景#

公司财务每个月都要汇总各部门的报表,几十个 Excel,格式还不统一。原来都是手工复制粘贴,一个人要干三天。

我用 pandas 写了个自动化脚本,现在半小时跑完,还能自动检查错误。

基础读取#

读取单个文件#

import pandas as pd
# 最简单的方式
df = pd.read_excel('data.xlsx')
# 指定工作表
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
# 跳过前几行(有些报表有标题)
df = pd.read_excel('data.xlsx', skiprows=3)
# 指定列
df = pd.read_excel('data.xlsx', usecols=['A', 'C', 'D'])

批量读取#

import glob
import pandas as pd
# 读取目录下所有 xlsx
files = glob.glob('data/*.xlsx')
dfs = []
for file in files:
df = pd.read_excel(file)
df['来源文件'] = file # 添加来源标记
dfs.append(df)
# 合并
result = pd.concat(dfs, ignore_index=True)

数据清洗#

处理缺失值#

# 查看缺失值
print(df.isnull().sum())
# 删除有缺失值的行
df_clean = df.dropna()
# 填充缺失值
df['金额'].fillna(0, inplace=True)
df['备注'].fillna('无', inplace=True)
# 用平均值填充
df['金额'].fillna(df['金额'].mean(), inplace=True)

去重#

# 查看重复
print(df.duplicated().sum())
# 删除完全重复的行
df = df.drop_duplicates()
# 按特定列去重
df = df.drop_duplicates(subset=['姓名', '日期'], keep='first')

类型转换#

# 字符串转数字
df['金额'] = pd.to_numeric(df['金额'], errors='coerce')
# 字符串转日期
df['日期'] = pd.to_datetime(df['日期'], format='%Y-%m-%d')
# 转字符串
df['编号'] = df['编号'].astype(str)

errors='coerce' 很重要,转换失败会变成 NaN,不会报错。

数据处理#

筛选数据#

# 单条件
df_large = df[df['金额'] > 1000]
# 多条件
df_filtered = df[(df['金额'] > 1000) & (df['日期'] >= '2024-01-01')]
# isin
df_depts = df[df['部门'].isin(['销售部', '市场部'])]
# 字符串匹配
df_names = df[df['姓名'].str.contains('张', na=False)]

分组统计#

# 按部门汇总
summary = df.groupby('部门')['金额'].sum()
# 多维度统计
summary = df.groupby(['部门', '月份']).agg({
'金额': ['sum', 'mean', 'count'],
'数量': 'sum'
})
# 重置索引
summary = summary.reset_index()

数据透视表#

# 类似 Excel 的数据透视表
pivot = pd.pivot_table(
df,
values='金额',
index='部门',
columns='月份',
aggfunc='sum',
fill_value=0
)

合并数据#

# 类似 SQL 的 join
df_merged = pd.merge(
df_left,
df_right,
on='员工ID',
how='left' # left, right, inner, outer
)
# 多列关联
df_merged = pd.merge(
df_left,
df_right,
on=['部门', '月份'],
how='inner'
)

实用技巧#

添加计算列#

# 简单计算
df['总额'] = df['单价'] * df['数量']
# 条件计算
df['折扣'] = df['金额'].apply(lambda x: 0.9 if x > 1000 else 1.0)
# 复杂逻辑
def calc_bonus(row):
if row['业绩'] >= 100000:
return row['业绩'] * 0.1
elif row['业绩'] >= 50000:
return row['业绩'] * 0.05
else:
return 0
df['奖金'] = df.apply(calc_bonus, axis=1)

数据校验#

# 检查异常值
errors = df[df['金额'] < 0]
if not errors.empty:
print(f"发现 {len(errors)} 条金额异常数据")
errors.to_excel('errors.xlsx', index=False)
# 检查必填项
required_cols = ['姓名', '部门', '金额']
for col in required_cols:
missing = df[df[col].isnull()]
if not missing.empty:
print(f"{col}{len(missing)} 条缺失")
# 数据一致性检查
df['校验'] = df['明细合计'] == df['总金额']
wrong = df[~df['校验']]

格式化输出#

# 设置显示选项
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', 100)
pd.set_option('display.float_format', '{:.2f}'.format)
# 导出 Excel,带格式
with pd.ExcelWriter('output.xlsx', engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='数据', index=False)
# 获取工作表
worksheet = writer.sheets['数据']
# 调整列宽
for column in worksheet.columns:
max_length = 0
column_letter = column[0].column_letter
for cell in column:
try:
if len(str(cell.value)) > max_length:
max_length = len(str(cell.value))
except:
pass
adjusted_width = min(max_length + 2, 50)
worksheet.column_dimensions[column_letter].width = adjusted_width

完整案例#

月度报表汇总#

import pandas as pd
import glob
from datetime import datetime
def process_monthly_report():
"""汇总各部门月度报表"""
# 1. 读取所有文件
files = glob.glob('reports/2024-*-*.xlsx')
print(f"找到 {len(files)} 个文件")
all_data = []
error_files = []
for file in files:
try:
# 读取数据
df = pd.read_excel(file)
# 标准化列名(有些文件列名不统一)
df.columns = df.columns.str.strip()
# 添加来源信息
df['来源文件'] = file
df['导入时间'] = datetime.now()
all_data.append(df)
except Exception as e:
error_files.append({'file': file, 'error': str(e)})
# 2. 合并数据
if not all_data:
print("没有成功读取的文件")
return
combined = pd.concat(all_data, ignore_index=True)
print(f"合并完成,共 {len(combined)} 条记录")
# 3. 数据清洗
# 删除空行
combined = combined.dropna(subset=['金额'])
# 金额转数值
combined['金额'] = pd.to_numeric(combined['金额'], errors='coerce')
combined = combined.dropna(subset=['金额'])
# 日期格式化
combined['日期'] = pd.to_datetime(combined['日期'], errors='coerce')
# 4. 数据校验
# 检查负数金额
negative = combined[combined['金额'] < 0]
if not negative.empty:
print(f"警告:发现 {len(negative)} 条负数金额")
negative.to_excel('negative_amounts.xlsx', index=False)
# 5. 生成汇总
summary = combined.groupby('部门').agg({
'金额': ['sum', 'mean', 'count']
}).round(2)
# 6. 导出结果
with pd.ExcelWriter('monthly_summary.xlsx', engine='openpyxl') as writer:
combined.to_excel(writer, sheet_name='明细数据', index=False)
summary.to_excel(writer, sheet_name='部门汇总')
if error_files:
pd.DataFrame(error_files).to_excel(writer, sheet_name='错误文件', index=False)
print("处理完成,结果已导出到 monthly_summary.xlsx")
return combined, summary
# 运行
if __name__ == '__main__':
process_monthly_report()

最后说两句#

pandas 功能很强大,但也容易把简单问题复杂化。

我的建议:

  1. 先想清楚要做什么,再写代码
  2. 小步测试,不要一次性处理太多数据
  3. 保存中间结果,方便排查问题
  4. 做好异常处理,真实数据总是乱七八糟的

还有,Excel 能做的事情不要硬上 pandas。有时候手动处理更快。


参考链接#


2026-03-09 更新。pandas 版本 2.2.x。