在日常办公和数据分析中,Excel和CSV文件就像空气一样无处不在。作为金融分析师,我每天要处理上百份交易记录报表;做电商运营的朋友每周都要合并几十家店铺的销售数据;而科研人员则经常需要清洗实验仪器导出的CSV数据。手动一个个打开文件操作不仅效率低下,还容易出错。
Python的pandas库正是解决这类问题的瑞士军刀。它能够:
最近我用这套方法帮市场部同事把原本需要8小时的手工报表合并工作压缩到了3分钟完成。下面分享具体实现方案和踩坑经验。
python复制import pandas as pd # 数据处理核心
import glob # 文件路径匹配
import os # 文件系统操作
这是最精简的工具组合。pandas是数据处理的核心引擎,glob用于快速获取文件列表,os模块处理路径相关操作。为什么不直接用os.listdir?因为glob支持通配符匹配,能更灵活地筛选特定格式文件。
当处理大型文件或特殊需求时,可以考虑:
openpyxl:处理xlsx格式的复杂Excel文件(带公式、图表等)xlrd:兼容旧版xls格式(但已停止维护)dask:处理超出内存的超大CSV文件pyexcel:需要同时处理多种格式时的统一接口提示:实际项目中建议先用pandas基准测试,遇到性能瓶颈再考虑其他方案。我测试过用pandas读取500MB的CSV文件,现代电脑通常只需10秒左右。
python复制# 获取所有xlsx文件路径
excel_files = glob.glob('./data/*.xlsx')
# 读取并合并多个Excel文件
df_list = []
for file in excel_files:
df = pd.read_excel(file, sheet_name='Sheet1')
df['source_file'] = os.path.basename(file) # 标记来源文件
df_list.append(df)
combined_df = pd.concat(df_list, ignore_index=True)
关键点说明:
sheet_name参数确保读取指定工作表ignore_index避免索引重复python复制all_csv_files = []
for root, dirs, files in os.walk('./data'):
for file in files:
if file.endswith('.csv'):
all_csv_files.append(os.path.join(root, file))
这种方案适合需要处理多层嵌套目录的情况。我在处理电商平台按日期分类的订单数据时,这种写法特别有用。
不同系统导出的日期格式各异,这是最常见的痛点:
python复制def standardize_date(date_str):
try:
# 尝试解析常见日期格式
return pd.to_datetime(date_str, format='%Y/%m/%d', errors='coerce') or \
pd.to_datetime(date_str, format='%d-%m-%Y', errors='coerce') or \
pd.to_datetime(date_str, format='%m.%d.%Y', errors='coerce')
except:
return pd.NaT
df['order_date'] = df['order_date'].apply(standardize_date)
python复制# 删除全空的行
df.dropna(how='all', inplace=True)
# 用分组均值填充数值型缺失值
df['price'] = df.groupby('product_category')['price'].transform(
lambda x: x.fillna(x.mean()))
注意:直接fillna()可能引入偏差,建议先分析缺失模式。金融数据中的缺失值往往需要特殊处理。
python复制# 计算每个产品的总销售额
summary = combined_df.groupby('product_id').agg({
'quantity': 'sum',
'amount': ['sum', 'mean', 'count']
}).reset_index()
# 扁平化多级列名
summary.columns = ['_'.join(col).strip() for col in summary.columns.values]
python复制# 标记异常订单
df['is_abnormal'] = np.where(
(df['amount'] > df['amount'].quantile(0.99)) |
(df['quantity'] <= 0),
1, 0
)
python复制# 按月份拆分输出
for month, group in df.groupby(pd.Grouper(key='order_date', freq='M')):
output_name = f"output/{month.strftime('%Y%m')}_report.xlsx"
group.to_excel(output_name, index=False)
python复制with pd.ExcelWriter('multi_sheet.xlsx') as writer:
summary.to_excel(writer, sheet_name='Summary')
raw_data.to_excel(writer, sheet_name='RawData')
pivot_table.to_excel(writer, sheet_name='Analysis')
处理GB级文件时,可以采用分块读取:
python复制chunk_size = 100000 # 10万行为一个块
chunks = pd.read_csv('huge_file.csv', chunksize=chunk_size)
for i, chunk in enumerate(chunks):
process(chunk) # 自定义处理函数
if i % 10 == 0:
print(f"已处理 {(i+1)*chunk_size} 行")
python复制dtype_mapping = {
'user_id': 'int32', # 默认int64占用双倍内存
'price': 'float32',
'description': 'category' # 低基数文本列
}
df = pd.read_csv('data.csv', dtype=dtype_mapping)
通过合理设置数据类型,我曾将2GB文件的内存占用从8GB降到1.2GB。
当遇到中文乱码时,可以尝试以下编码方式:
python复制encodings = ['utf-8', 'gbk', 'gb2312', 'big5', 'latin1']
for enc in encodings:
try:
df = pd.read_csv('data.csv', encoding=enc)
break
except UnicodeDecodeError:
continue
python复制# 强制指定日期列
df = pd.read_excel('data.xlsx', parse_dates=['order_date', 'payment_date'])
# 处理混合日期格式
df['date_column'] = pd.to_datetime(df['date_column'], errors='coerce')
pd.read_csv(..., usecols=['col1','col2'])只读取必要列dtype参数优化数据类型chunksize分块处理最近完成的真实项目需求:
核心代码结构:
python复制def process_sales_reports(input_dir, output_dir):
# 1. 文件收集
csv_files = glob.glob(f"{input_dir}/*_sales_*.csv")
# 2. 数据合并与清洗
combined = pd.concat([pd.read_csv(f) for f in csv_files])
combined = clean_data(combined) # 自定义清洗函数
# 3. 业务计算
report = generate_kpi_report(combined)
# 4. 输出结果
report.to_excel(f"{output_dir}/daily_report.xlsx")
generate_plots(report) # 生成可视化图表
这个方案使原本需要4小时的手工操作缩短到2分钟自动完成,且消除了人为错误。关键收获是:一定要在清洗阶段添加完善的数据校验逻辑,比如检查销售额=单价×数量是否成立。