如何在Pandas透视表中使用分组函数及按固定时间段分组
嘿,我来帮你搞定这两个Pandas的问题,都是实际数据分析里很常用的场景哦!
1. 如何在Pandas透视表中使用分组函数?
Pandas的pivot_table本身就支持通过aggfunc参数指定分组聚合逻辑,不管是内置函数还是自定义函数都能搞定,甚至还能结合groupby先做更细的分组再生成透视表。给你几个实用的例子:
先准备示例数据
import pandas as pd import numpy as np # 构造测试数据 df = pd.DataFrame({ 'Category': ['A', 'A', 'B', 'B', 'A', 'B'], 'Subcategory': ['X', 'Y', 'X', 'Y', 'X', 'Y'], 'Value': [10, 20, 15, 25, 30, 35] })
用内置聚合函数做透视表
最基础的用法,直接给aggfunc传内置的统计函数,比如求和、均值,甚至可以传一个列表同时用多个函数:
# 同时计算求和和均值的透视表 pivot_basic = pd.pivot_table(df, index='Category', columns='Subcategory', values='Value', aggfunc=[np.sum, np.mean]) print(pivot_basic)
自定义分组聚合函数
如果内置函数满足不了需求,比如想计算每组的极差(最大值减最小值),可以自己写个函数传给aggfunc:
# 自定义聚合函数:计算数值范围 def calculate_range(x): return x.max() - x.min() # 应用自定义函数的透视表 pivot_custom = pd.pivot_table(df, index='Category', columns='Subcategory', values='Value', aggfunc=calculate_range) print(pivot_custom)
先分组再做透视表
如果需要先按某个维度分组,再对每个子组单独生成透视表,可以结合groupby和apply:
# 先按Category分组,每个组内生成透视表 grouped_pivot = df.groupby('Category').apply( lambda group: pd.pivot_table(group, index='Subcategory', values='Value', aggfunc=np.sum) ) print(grouped_pivot)
2. 按固定1小时时间段分组时间字段作为透视表索引
你的场景是把hh:mm:ss.ms格式的时间按12:30-13:30、13:30-14:30这类固定区间分组,核心是先把时间转成datetime类型,再用区间切割来生成分组标签,最后用这个标签做透视表索引。
步骤拆解+代码示例
import pandas as pd # 构造你的示例数据 df_time = pd.DataFrame({ 'ActualTime': ['12:30', '12:31', '12:46', '13:05', '13:22', '13:48', '14:05'], 'Value': [5, 8, 3, 10, 7, 12, 6] }) # 第一步:把时间字符串转成datetime类型(如果有毫秒,格式改成'%H:%M:%S.%f') df_time['ActualTime'] = pd.to_datetime(df_time['ActualTime'], format='%H:%M') # 第二步:生成自定义时间区间 start_time = pd.to_datetime('12:30', format='%H:%M') # 起始区间点 interval_hours = 1 # 每个区间1小时 # 用pd.cut切割时间,生成区间分组 df_time['TimeInterval'] = pd.cut( df_time['ActualTime'], bins=pd.date_range(start=start_time, end=df_time['ActualTime'].max() + pd.Timedelta(hours=interval_hours), freq=f"{interval_hours}H"), right=False, # 左闭右开:比如12:30<=时间<13:30归为第一个区间 include_lowest=True # 确保第一个时间点12:30被包含进去 ) # 第三步:把区间标签格式化成你要的"hh:mm-hh:mm"样式 df_time['TimeInterval'] = df_time['TimeInterval'].apply( lambda x: f"{x.left.strftime('%H:%M')}-{x.right.strftime('%H:%M')}" ) # 第四步:生成以时间段为索引的透视表(这里以求和为例,你可以换其他聚合函数) time_pivot = pd.pivot_table(df_time, index='TimeInterval', values='Value', aggfunc=np.sum) print(time_pivot)
运行后会得到这样的结果:
Value TimeInterval 12:30-13:30 33 13:30-14:30 18
如果你的时间字段包含毫秒,只需要把pd.to_datetime的format参数改成'%H:%M:%S.%f'就行,其他逻辑完全通用。
内容的提问来源于stack exchange,提问作者Kartik




