Python案例实战:如何用Pandas高效完成数据分组与重采样(废弃值处理指南)
目录导读
背景与痛点:为什么要掌握分组重采样?
在实际数据分析工作中,我们经常面对这样的场景:原始数据是秒级或分钟级的时间序列,但业务需求却是按周、按月统计不同类别的汇总指标,数据中可能包含大量“废弃值”——比如异常值、缺失值或业务不再需要的过期记录。

Pandas 的 groupby 结合 resample 是解决这类问题的利器,通过分组重采样,你可以:
- 将高频率数据降采样为低频率(如从“天”到“月”)
- 按类别(如产品线、区域)独立计算统计量
- 清洗或标记废弃值,避免污染最终结果
根据谷歌SEO最佳实践,本文会从实际案例出发,给出可直接复用的代码模板,并解答常见误解。
核心概念解析:分组、重采样、废弃值
1 分组 (GroupBy)
Pandas 的 groupby 允许你按照一个或多个键拆分数据,然后对每个分组独立执行函数。df.groupby('category')['sales'].sum()
2 重采样 (Resample)
resample 专门用于时间序列数据,可以改变时间频率,常用参数:
rule:目标频率,如'W'(周)、'M'(月末)closed:区间闭合方式label:结果标签位置
3 废弃值 (Discarded/Outdated Values)
这里指两类:
- 显式废弃:业务上不再使用的记录(如已取消订单)
- 隐式废弃:异常值或缺失值,需要在聚合前剔除
注意:正确的做法是通过 dropna() 或条件筛选先清理废弃值,再执行重采样,而不是事后补救。
案例场景:电商销售数据的周度汇总
假设我们有一份电商平台的销售记录,包含以下字段:
order_time:订单时间(datetime)product_category:商品类别(如“电子产品”、“服装”)sales_amount:销售额(float)is_cancelled:是否已取消(废弃标记)
目标:
按“商品类别”分组,对“未取消订单”进行周度销售额汇总,并剔除没有交易的周。
数据样例:
import pandas as pd
data = {
'order_time': pd.date_range('2024-01-01', periods=20, freq='D'),
'product_category': ['A','B','A','B','A','B']*3 + ['A','B'],
'sales_amount': [100,200,150,np.nan,130,210,180,190,220,140]*2,
'is_cancelled': [0,0,1,0,0,0,1,0,0,0]*2
}
df = pd.DataFrame(data)
这里 is_cancelled=1 表示废弃订单,sales_amount 中的 NaN 也属于废弃值。
代码实操:从数据分组到重采样完整链条
Step 1:数据预处理——剔除废弃值
# 移除被取消的订单(废弃记录) df_clean = df[df['is_cancelled'] == 0].copy() # 移除销售额缺失的行(废弃数值) df_clean = df_clean.dropna(subset=['sales_amount'])
Step 2:设置时间索引
df_clean.set_index('order_time', inplace=True)
Step 3:分组 + 重采样(核心操作)
# 按类别分组,并按周重采样,计算销售额总和
weekly_sum = df_clean.groupby('product_category').resample('W')['sales_amount'].sum()
此时得到的结果类似:
product_category order_time
A 2024-01-07 380.0
2024-01-14 400.0
B 2024-01-07 210.0
2024-01-14 190.0
Step 4:处理无交易的周(填充或丢弃)
# 用0填充没有数据的周,或者直接重设索引 weekly_sum = weekly_sum.fillna(0).reset_index()
完整代码封装:
def weekly_category_summary(df, date_col='order_time', cat_col='product_category',
val_col='sales_amount', flag_col='is_cancelled'):
df = df[df[flag_col] == 0].dropna(subset=[val_col])
df.set_index(date_col, inplace=True)
result = df.groupby(cat_col).resample('W')[val_col].sum().fillna(0)
return result.reset_index()
常见问题与问答集锦
Q1:如果数据本身不是时间索引,能直接重采样吗?
不能,必须先通过 set_index 将时间列设为索引,否则 resample 会报错,常见解法是使用 pd.to_datetime() 转换列后再操作。
Q2:废弃值到底应该在分组前还是分组后删除?
分组前,如果在 groupby 之后通过 apply 删除废弃值,会导致索引错乱和性能下降,更优方案是先全量清洗,再分组重采样。
Q3:resample 和 groupby 的顺序可以交换吗?
不可以,逻辑上必须“先分组,再重采样”,否则时间频率变换会打乱类别统计。df.resample('W').groupby('category').sum() 会先降采样所有数据再分组,结果完全错误。
Q4:如何重采样为“每两周”或“每季度”?
修改 rule 参数即可:
- 每两周:
'2W' - 季度:
'Q' - 自定义:
pd.offsets.Week(2)或pd.offsets.MonthEnd(3)
SEO优化建议与延伸阅读
关键词布局:
本文主要关键词“Pandas 分组重采样废弃值”在标题、首段、H2小标题中自然出现3-4次,段落内穿插“Pandas案例”、“时间序列处理”、“数据清洗”等长尾词。
内链建议:
如果你正在搭建数据分析博客,可以链接以下相关文章:
- Pandas时间序列完全指南
- 10个必须知道的GroupBy高级用法
- 数据清洗:如何自动检测异常值
用户常见搜索意图:
- “pandas groupby resample example”
- “pandas remove outliers before resample”
- “python weekly aggregation by category”
最终验证:
建议将上述代码复制到 Jupyter Notebook 或 Google Colab 中运行,并尝试修改 rule 参数为 'M' 或 'D',观察结果变化,只有动手实践,才能深刻理解分组重采样的精髓。
本文综合了 Pandas 官方文档、Stack Overflow 高频问答以及中文技术社区的最佳实践,经过二次加工形成可直接落地的案例。