如何高效对含category变量的DataFrame进行hourly resampling?
解决Pandas按小时重采样并保留分类变量的问题
我懂你遇到的痛点——用resample('h').sum()的时候,分类(category)类型的列会被直接丢弃,因为sum聚合函数只处理数值型数据。针对你的需求,这里有两种高效的实现方式,完美匹配你的示例场景:
先看你的示例数据代码:
import pandas as pd date = ['2015-02-03 23:00:00','2015-02-03 23:30:00','2015-02-04 00:00:00','2015-02-04 00:30:00'] value = [33.24 , 31.71 , 34.39 , 34.49 ] value2 = [2*x for x in value] value3 = [3*x for x in value] cat = ['a','a','b','b'] df = pd.DataFrame({'value':value,'value2':value2,'value3':value3,'index':date,'category':cat}) df.index = pd.to_datetime(df['index'],format='%Y-%m-%d %H:%M') df.drop(['index'],axis=1,inplace=True) print(df.head())
输出结果:
value value2 value3 category index 2015-02-03 23:00:00 33.24 66.48 99.72 a 2015-02-03 23:30:00 31.71 63.42 95.13 a 2015-02-04 00:00:00 34.39 68.78 103.17 b 2015-02-04 00:30:00 34.49 68.98 103.47 b
你的预期结果:
value value2 value3 category index 2015-02-03 23:00:00 64.95 129.90 194.85 a 2015-02-04 00:00:00 68.88 137.76 206.64 b
方法一:用groupby + Grouper(推荐,逻辑清晰)
因为你的同一小时内的分类变量是一致的,我们可以把时间分组器和分类列一起作为groupby的键,聚合后再把分类列恢复为普通列:
# 按小时和分类分组,求和后重置分类列的索引层级 df_resampled = df.groupby([pd.Grouper(freq='h'), 'category']).sum().reset_index(level='category')
这样处理后,既完成了数值列的小时求和,又完整保留了分类列,完全符合你的预期。
方法二:用resample.agg()指定列级聚合规则
这种方式更灵活,你可以为不同列指定不同的聚合逻辑——数值列用sum,分类列用first(因为同一小时内分类相同,取第一个即可)或者mode(如果同一小时可能有不同分类,取出现次数最多的):
# 定义各列的聚合规则 agg_rules = { 'value': 'sum', 'value2': 'sum', 'value3': 'sum', 'category': 'first' # 或者用 lambda x: x.mode()[0] 处理可能的多分类情况 } # 按小时重采样并应用聚合规则 df_resampled = df.resample('h').agg(agg_rules)
如果你的场景中同一小时内可能出现多个不同的分类值,想要取众数的话,可以把'category': 'first'改成'category': lambda x: x.mode()[0],这样能确保取到出现次数最多的分类。
两种方法都能高效完成需求,你可以根据自己的实际场景选择——如果分类在时间段内完全一致,方法一更简洁;如果需要更精细的列控制,方法二更合适。
内容的提问来源于stack exchange,提问作者Peslier53
相关产品推荐
相关产品推荐

