Pandas Datetime聚合:如何计算前日、上周同日及周均值?
实现前日均值、上周同日均值及周均值的聚合方案
看起来你已经搞定了当日均值的计算,接下来要扩展到前日、上周同日和周均值对吧?我给你整理几个实用的实现方案,都是基于Pandas的常规操作,容易理解也高效:
前置准备:确保日期格式正确
首先得保证你的day列是datetime格式,不然日期偏移、周计算这些操作会报错。如果还没转换,先执行:
import pandas as pd data['day'] = pd.to_datetime(data['day'])
一、计算前日均值
思路是:先预计算每个站点每日的均值,再把这些均值映射到次日的记录上(也就是当前记录的前日均值)。具体步骤:
- 先生成所有站点的每日均值表:
# 计算每个站点每日的consomation和temperature均值 daily_means = data.groupby(['site', 'day']).agg( consomation_daily=('consomation', 'mean'), temperature_daily=('temperature', 'mean') ).reset_index()
- 把每日均值表的日期往后推1天,再和原数据合并,得到每条记录的前日均值:
# 给每日均值表添加「次日」字段,用来匹配原数据的当前日期 daily_means['next_day'] = daily_means['day'] + pd.Timedelta(days=1) # 合并到原数据,映射前日均值 data = data.merge( daily_means[['site', 'next_day', 'consomation_daily', 'temperature_daily']], left_on=['site', 'day'], right_on=['site', 'next_day'], how='left' # 用left join避免丢失原数据行 ).rename(columns={ 'consomation_daily': 'consomation_prev_day', 'temperature_daily': 'temperature_prev_day' }).drop('next_day', axis=1)
如果某条记录没有前日数据(比如数据集的第一天),对应的均值会显示NaN,这是合理的。
二、计算上周同日均值
和前日均值思路类似,只是把日期偏移改成7天,找到当前日期的上周同一天:
# 给每日均值表添加「上周同日的次日」字段(也就是当前日期) daily_means['last_week_same_day_next'] = daily_means['day'] + pd.Timedelta(days=7) # 合并到原数据,映射上周同日均值 data = data.merge( daily_means[['site', 'last_week_same_day_next', 'consomation_daily', 'temperature_daily']], left_on=['site', 'day'], right_on=['site', 'last_week_same_day_next'], how='left' ).rename(columns={ 'consomation_daily': 'consomation_last_week_same_day', 'temperature_daily': 'temperature_last_week_same_day' }).drop('last_week_same_day_next', axis=1)
比如2012-11-27的上周同日就是2012-11-20,这个方法会自动匹配对应站点的当日均值。
三、计算周均值(两种常见场景)
周均值通常有两种需求,我分别给你实现:
场景1:自然周均值(按周一到周日/周日到周六的完整周计算)
用ISO周(国际标准周,周一为一周第一天)来分组,结合年份避免跨年周混淆:
# 添加年和周的标识列 data['year'] = data['day'].dt.isocalendar().year data['week'] = data['day'].dt.isocalendar().week # 用transform直接给每条记录赋值所在周的均值 data['consomation_week_mean'] = data.groupby(['site', 'year', 'week'])['consomation'].transform('mean') data['temperature_week_mean'] = data.groupby(['site', 'year', 'week'])['temperature'].transform('mean')
这个方法很简洁,每条记录都会带上自己所在自然周的站点均值。
场景2:滚动7天均值(过去7天的滑动窗口均值)
如果需要的是以当前日期为终点,过去7天内的均值(比如包含当天或不包含),可以用滚动窗口:
# 先按站点和日期排序,确保时间顺序正确 data = data.sort_values(['site', 'day']) # 计算滚动7天均值(window='7D'表示7天时间窗口,closed='left'表示不包含当天) data['consomation_7day_rolling'] = data.groupby('site').rolling( window='7D', on='day', closed='left' )['consomation'].mean().reset_index(level=0, drop=True) data['temperature_7day_rolling'] = data.groupby('site').rolling( window='7D', on='day', closed='left' )['temperature'].mean().reset_index(level=0, drop=True)
如果想要包含当天,去掉closed='left'即可(默认是'right',包含窗口终点)。
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

