Pandas 高级操作:分组聚合、透视表与时间序列

FreeGuideOnline 最新 2026-06-16

Pandas 高级操作:分组聚合、透视表与时间序列

欢迎来到本教程!如果你已经掌握了 Pandas 的基础知识(数据读取、筛选、排序和简单统计),那么是时候深入探索那些真正让数据分析工作流变得高效的“高级操作”了。本教程将聚焦于三大核心模块:分组聚合透视表 以及 时间序列处理。我们将用清晰的代码示例与实际场景,帮助你彻底理解这些概念。

1. 分组聚合:超越 groupby() 的基础用法

分组聚合是数据分析中最强大的手段之一,它遵循“分割-应用-合并”的模式。我们先从增强版的聚合开始。

1.1 多函数聚合与自定义函数

groupby().agg() 允许对不同的列应用不同的聚合函数。你可以传入字典来指定列与函数的映射,甚至传入自定义函数。

import pandas as pd
import numpy as np

# 示例数据:电商销售记录
df = pd.DataFrame({
    '类别': ['电子产品', '服装', '电子产品', '服装', '电子产品'],
    '子类别': ['手机', '上衣', '笔记本电脑', '裤子', '手机'],
    '销售额': [200, 150, 800, 120, 300],
    '利润': [50, 40, 150, 30, 80]
})

# 对不同列使用不同的聚合方式
result = df.groupby('类别').agg(
    总销售额=('销售额', 'sum'),
    平均利润=('利润', 'mean'),
    最高销售额=('销售额', 'max'),
    销售笔数=('销售额', 'count')
).reset_index()
print(result)

还可以使用 agg 配合 NumPy 函数或自定义 lambda 函数:

# 计算销售额的极差(最大值-最小值)
grouped = df.groupby('类别')['销售额'].agg(
    ['sum', 'mean', lambda x: x.max() - x.min()]
)
grouped.columns = ['总和', '均值', '极差']

1.2 变换操作:transform 的妙用

transformagg 的关键区别在于,它返回与原 DataFrame 索引一致、长度相同的数据。这对“组内标准化”或“填充缺失值”非常有用。

场景:计算每个类别内部的销售额相对于该类别平均销售额的比例。

df['销售额组内均值'] = df.groupby('类别')['销售额'].transform('mean')
df['销售额偏离均值'] = df['销售额'] - df['销售额组内均值']
print(df[['类别', '销售额', '销售额组内均值', '销售额偏离均值']])

场景:用组内平均值填充该组内的缺失值。(先模拟缺失值)

df.loc[1, '利润'] = np.nan  # 人为制造一个缺失值
df['利润'] = df.groupby('类别')['利润'].transform(lambda x: x.fillna(x.mean()))

1.3 过滤操作:filter

filter 可以根据组的整体属性来筛选整个组,而不是组内的行。例如,保留销售额总和大于 500 的类别。

filtered_df = df.groupby('类别').filter(lambda g: g['销售额'].sum() > 500)
print(filtered_df)

2. 透视表与交叉表:灵活重塑数据

透视表是 Excel 用户非常熟悉的功能,Pandas 中的 pivot_table 更强大且可编程。

2.1 创建透视表

语法:pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', ...)

我们用一个新的销售数据集来说明:

sales_data = pd.DataFrame({
    '月份': ['1月', '1月', '1月', '2月', '2月', '2月'],
    '地区': ['华北', '华东', '华南', '华北', '华东', '华南'],
    '产品': ['A', 'A', 'B', 'A', 'B', 'B'],
    '销售额': [100, 150, 200, 110, 160, 190]
})

默认聚合函数是平均值,我们可以改成 sum 来得到汇总:

pivot = pd.pivot_table(sales_data, 
                       values='销售额', 
                       index='月份', 
                       columns='地区', 
                       aggfunc='sum',
                       fill_value=0)  # 用0填充NaN
print(pivot)

2.2 多值透视与边际汇总

你可以计算多个值字段,并且添加“合计”行列 (margins=True)。

# 增加一列利润数据
sales_data['利润'] = sales_data['销售额'] * 0.2

pivot_multi = pd.pivot_table(sales_data,
                             values=['销售额', '利润'],
                             index=['月份'],
                             columns=['地区'],
                             aggfunc='sum',
                             margins=True,
                             margins_name='总计')
print(pivot_multi)

2.3 交叉表:crosstab

交叉表是专门计算分组频率的特殊透视表,常用于统计列联表。

# 用户行为数据
users = pd.DataFrame({
    '性别': ['男', '女', '男', '男', '女'],
    '偏好': ['科技', '时尚', '科技', '科技', '时尚'],
    '年龄段': ['青年', '青年', '中年', '青年', '中年']
})

# 统计性别与偏好的频次
cross = pd.crosstab(users['性别'], users['偏好'])
print(cross)

# 更高级:多列交叉,并显示总计
cross_norm = pd.crosstab(users['性别'], [users['年龄段'], users['偏好']], 
                         margins=True, normalize='index')  # 按行归一化
print(cross_norm)

3. 时间序列高级处理

Pandas 拥有卓越的时间序列功能,掌握它能让金融、物联网、日志等数据的处理事半功倍。

3.1 时间索引与日期功能

首先,确保数据带有正确的时间索引,并使用 DatetimeIndex

date_rng = pd.date_range(start='2024-01-01', end='2024-01-10', freq='D')
ts_df = pd.DataFrame(date_rng, columns=['日期'])
ts_df['销售额'] = np.random.randint(100, 500, size=len(date_rng))
ts_df.set_index('日期', inplace=True)

利用日期属性提取特征:

ts_df['星期'] = ts_df.index.dayofweek  # 0=周一
ts_df['是否周末'] = ts_df['星期'].isin([5,6]).astype(int)
ts_df['月份'] = ts_df.index.month

3.2 重采样:改变时间频率

resample() 是时间序列分组的利器。降采样(从高频到低频)需要聚合,升采样(从低频到高频)需要插值。

降采样:日数据聚合为周数据

weekly_sales = ts_df.resample('W-MON')['销售额'].agg(['sum', 'mean', 'count'])
print(weekly_sales)

其中 'W-MON' 表示以周一作为每周的起始日。常用的频率有 'D' 天,'H' 小时,'M' 月末,'Q' 季末,'A' 年末等。

升采样与插值

# 创建一个小数据集,从2天数据升采样到每小时数据
daily = pd.DataFrame({
    '值': [10, 20]
}, index=pd.to_datetime(['2024-01-01', '2024-01-02']))

hourly = daily.resample('H').asfreq()  # 产生NaN
hourly_interpolated = hourly.resample('H').interpolate(method='linear')
print(hourly_interpolated.head())

3.3 滑动窗口计算:rolling

移动窗口常用于计算移动平均、移动标准差,消除噪声。

# 7天移动平均销售额
ts_df['7天移动平均'] = ts_df['销售额'].rolling(window=7, min_periods=1).mean()

# 计算滑动窗口内的标准差
ts_df['7天移动标准差'] = ts_df['销售额'].rolling(window=7).std()

rolling 也支持时间偏置窗口(rolling 结合时间索引):

# 基于时间的窗口,例如滚动2天窗口(需要考虑观测的时间密度)
# 如果索引是日期时间,可以这样:
# ts_df.rolling('2D').mean()

3.4 时间位移与滞后

使用 shift() 可以轻松创建滞后特征,常用于时间序列预测。

ts_df['前一日销售额'] = ts_df['销售额'].shift(1)
ts_df['前两日销售额'] = ts_df['销售额'].shift(2)
# 向前移动(未来值)
ts_df['后一日销售额'] = ts_df['销售额'].shift(-1)

3.5 日期范围生成与业务日

pd.bdate_range 生成工作日序列,适合金融分析。

bus_days = pd.bdate_range(start='2024-01-01', periods=10)
# 合并自定义假日
from pandas.tseries.holiday import USFederalHolidayCalendar
cal = USFederalHolidayCalendar()
holidays = cal.holidays(start='2024-01-01', end='2024-12-31')
bus_days_us = pd.bdate_range(start='2024-01-01', periods=10, holidays=holidays)

综合实例:销售仪表板数据准备

让我们将上述技术组合起来,完成一个接近实际工作的任务:有原始订单数据,需要生成按月、地区的销售汇总,并计算月环比增长率。

# 构造原始订单数据
np.random.seed(42)
n = 200
orders = pd.DataFrame({
    'order_date': pd.date_range('2024-01-01', periods=n, freq='D'),
    'region': np.random.choice(['北区', '南区', '东区', '西区'], n),
    'sales': np.random.randint(50, 500, n)
})

# 按月汇总
orders['月份'] = orders['order_date'].dt.to_period('M')  # 周期类型,方便排序
monthly_region = orders.groupby(['月份', 'region']).agg(
    月销售额=('sales', 'sum')
).reset_index()

# 创建透视表
pivot_region = pd.pivot_table(monthly_region, 
                              values='月销售额', 
                              index='月份', 
                              columns='region', 
                              aggfunc='sum', 
                              fill_value=0)
print("各地区月度销售额透视表:")
print(pivot_region)

# 计算月环比增长率(对所有地区列应用pct_change)
growth_pivot = pivot_region.pct_change() * 100
print("\n月环比增长率(%):")
print(growth_pivot.round(2))

# 利用时间序列重采样验证总销售额趋势
ts = orders.set_index('order_date')['sales'].resample('M').sum()
print("\n总月度销售额:")
print(ts)

结语

通过本教程,你已经掌握了 Pandas 在分组聚合、透视表重构和时间序列分析方面的核心高级技巧。这些操作是构建高效数据管道和进行深入探索性分析的基石。建议你下载本页代码示例,用你自己的数据集练习,并查阅 Pandas 官方文档中关于 groupby 增强功能、resample 偏移别名以及窗口函数的更多参数。不断实践,你将成为数据处理的高手!

本教程由「免费在线教程」提供,欢迎访问我们的其他课程。