如何在Pandas中按Category分组获取当前时间前n天同时刻数据
问题描述
我有如下时间序列数据,希望先按category分组,之后在每个分组内,获取当前时间前n天(此处以n=1为例)同一时刻对应的数据。
如果不分组,我可以用data.rolling(window='1D', closed='both', on='time').apply(lambda x:x[0])实现,但分组后不知道怎么操作,请问该如何实现?
示例数据
import pandas as pd data1 = {'time': ['2020-01-01 00:00:00', '2020-01-01 04:00:00', '2020-01-01 08:00:00', '2020-01-01 12:00:00', '2020-01-01 16:00:00', '2020-01-01 20:00:00', '2020-01-02 00:00:00', '2020-01-02 04:00:00', '2020-01-02 08:00:00', '2020-01-02 12:00:00', '2020-01-02 16:00:00', '2020-01-02 20:00:00', '2020-01-03 00:00:00', '2020-01-03 04:00:00', '2020-01-03 08:00:00', '2020-01-03 12:00:00', '2020-01-03 16:00:00', '2020-01-03 20:00:00', '2020-01-04 00:00:00', '2020-01-04 04:00:00'], 'category': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c'], 'nums': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]} df = pd.DataFrame(data1)
解决方案
方法1:分组后通过时间特征匹配
先提取时间的时分部分作为同一时刻的匹配依据,再在分组内关联前n天的对应数据:
# 转换time列为datetime类型 df['time'] = pd.to_datetime(df['time']) # 提取时分信息,用于匹配同一时刻 df['time_of_day'] = df['time'].dt.time def extract_prev_day_data(group, n=1): # 计算当前时间前n天的时间点 group['prev_day_time'] = group['time'] - pd.Timedelta(days=n) # 合并分组内数据,匹配前n天同一时刻的记录 merged = pd.merge( group, group, left_on=['category', 'prev_day_time', 'time_of_day'], right_on=['category', 'time', 'time_of_day'], suffixes=('', '_prev') ) return merged[['time', 'category', 'nums', 'nums_prev']] # 分组应用函数 result = df.groupby('category', group_keys=False).apply(extract_prev_day_data, n=1) print(result)
方法2:分组后直接使用rolling窗口
保留你原本的rolling思路,只需在分组后调用即可,注意先对分组内的时间排序:
df['time'] = pd.to_datetime(df['time']) # 按分组和时间排序,确保窗口计算正确 df = df.sort_values(['category', 'time']) # 分组后应用rolling窗口,取窗口内第一条数据(前1天同一时刻的值) df['nums_prev'] = df.groupby('category').rolling( window='1D', closed='both', on='time' )['nums'].apply(lambda x: x.iloc[0] if len(x) >= 2 else None).reset_index(level=0, drop=True) print(df)
方法3:固定时间间隔下使用shift偏移
如果数据是固定间隔采样(比如示例中每4小时一条,1天共6条),可以直接通过shift按行数偏移:
df['time'] = pd.to_datetime(df['time']) df = df.sort_values(['category', 'time']) # 计算1天对应的行数:24小时 / 4小时间隔 = 6行 n_days = 1 shift_rows = n_days * 6 # 分组后偏移对应行数 df['nums_prev'] = df.groupby('category')['nums'].shift(shift_rows) print(df)
内容的提问来源于stack exchange,提问作者green jim
相关产品推荐
相关产品推荐

