别光看教程了!用Pandas处理你的第一个真实数据集(从CSV导入到清洗完整流程)
别光看教程了!用Pandas处理你的第一个真实数据集(从CSV导入到清洗完整流程)
当你第一次打开Jupyter Notebook,输入import pandas as pd时,可能已经看过无数Pandas教程。但面对实际业务中那份格式混乱的CSV文件,依然会手足无措——为什么数据总读不完整?为什么合并表格时出现诡异错误?这就是真实世界的数据分析:没有完美样本,只有各种"脏数据"的实战考验。本文将带你用Pandas处理一份模拟电商订单数据(包含典型问题:缺失值、异常日期、重复记录),最终输出可分析的数据集。
1. 实战环境准备与数据概览
工欲善其事,必先利其器。推荐使用Jupyter Lab作为交互环境(比传统Notebook更强大的模块化界面),配合以下工具链:
# 创建虚拟环境(避免包冲突) python -m venv pandas_venv source pandas_venv/bin/activate # Linux/Mac pandas_venv\Scripts\activate # Windows # 安装核心库 pip install pandas numpy matplotlib jupyterlab我们的示例数据集dirty_orders.csv模拟了真实业务场景,包含以下典型问题:
- 第3行金额列存在
$1,200.50这样的货币符号 - 第7、15行的客户ID为
NaN - 第10-12行的日期格式混用
2023/01/15和15-Jan-2023 - 第20行重复记录了相同的订单
提示:实际工作中应先使用
head()和info()快速扫描数据,而非直接开始清洗。这能避免因盲目操作导致的二次污染。
2. 数据导入的陷阱与解决方案
直接使用pd.read_csv()可能会遇到以下常见问题:
| 问题类型 | 错误表现 | 解决方案 |
|---|---|---|
| 编码错误 | UnicodeDecodeError | 指定encoding='utf-8'或'gbk' |
| 自动类型推断失败 | 数字被识别为字符串 | 设置dtype={'amount': float} |
| 分隔符识别错误 | 所有数据挤在一列 | 明确sep=','或自定义分隔符 |
| 注释行干扰 | 首行被误认为列名 | 使用comment='#'跳过注释行 |
针对我们的数据集,使用增强版导入方式:
import numpy as np df = pd.read_csv( 'dirty_orders.csv', parse_dates=['order_date'], # 自动解析日期列 thousands=',', # 处理千分位符 na_values=['NA', 'N/A'], # 扩展缺失值标识 converters={ 'amount': lambda x: float(x.replace('$', '')) # 自定义金额清洗 } ) print(f"原始数据形状: {df.shape}")3. 数据清洗的五个关键步骤
3.1 处理缺失值的智能策略
缺失值处理不是简单删除,需分场景决策:
诊断缺失模式:
# 可视化缺失分布 import seaborn as sns sns.heatmap(df.isnull(), cbar=False)针对性处理:
- 客户ID缺失:标记为
"匿名客户"(业务需求) - 数值列缺失:用同品类中位数填充
df['customer_id'].fillna('匿名客户', inplace=True) df['amount'] = df.groupby('product_category')['amount'].transform( lambda x: x.fillna(x.median()))- 客户ID缺失:标记为
3.2 日期格式的统一化处理
混用日期格式会导致时间序列分析失效:
# 方法1:强制统一格式(适合明确知道正确格式) df['order_date'] = pd.to_datetime(df['order_date'], format='%Y/%m/%d') # 方法2:智能解析(适合不确定格式的情况) df['order_date'] = pd.to_datetime( df['order_date'], infer_datetime_format=True, errors='coerce' # 转换失败设为NaT ) # 移除无效日期行 df = df[df['order_date'].notna()]3.3 异常值的检测与处理
使用描述性统计和业务规则双重验证:
stats = df['amount'].describe() iqr = stats['75%'] - stats['25%'] upper_bound = stats['75%'] + 1.5 * iqr # 业务规则:单笔订单不超过10000元 df = df[(df['amount'] <= upper_bound) & (df['amount'] <= 10000)]4. 数据转换与增强
清洗后的数据需要结构化处理才能发挥价值:
4.1 创建衍生特征
# 从日期提取周数/季度 df['order_week'] = df['order_date'].dt.isocalendar().week df['order_quarter'] = df['order_date'].dt.quarter # 金额分段(用于分析客户消费层级) bins = [0, 100, 500, 1000, np.inf] labels = ['<100', '100-500', '500-1000', '>1000'] df['amount_tier'] = pd.cut(df['amount'], bins=bins, labels=labels)4.2 数据透视与聚合
生成各品类周销售报表:
weekly_sales = pd.pivot_table( df, values='amount', index='product_category', columns='order_week', aggfunc=['sum', 'count'], margins=True )5. 成果输出与自动化脚本
最终输出清洗后的数据和分析报表:
# 保存清洗结果 df.to_csv('cleaned_orders.csv', index=False) # 生成带格式的Excel报告 with pd.ExcelWriter('sales_report.xlsx') as writer: df.to_excel(writer, sheet_name='Cleaned Data') weekly_sales.to_excel(writer, sheet_name='Weekly Summary') # 添加Excel图表 workbook = writer.book worksheet = writer.sheets['Weekly Summary'] chart = workbook.add_chart({'type': 'column'}) chart.add_series({ 'values': '=Weekly Summary!$B$2:$E$2', 'categories': '=Weekly Summary!$B$1:$E$1' }) worksheet.insert_chart('G2', chart)注意:实际项目中建议将清洗流程封装为函数,并使用
pd.pipe()实现链式调用。例如:
def clean_data(df): return ( df.pipe(handle_missing) .pipe(format_dates) .pipe(remove_outliers) )