Pandas按id分组补全时间步后如何将同组数据转为单行?
Pandas 固定时间步缺失补全+长表转宽表实现
问题说明
给定包含id、val、date三列的DataFrame,每个id对应单日5个固定时间步(6:00、6:15、6:30、6:45、7:00),部分id存在时间步缺失,需要将缺失位置填充为NaN,最终输出每个id占一行的宽表,每个时间步的val单独成列。
测试数据构造代码如下:
import pandas as pd df = pd.DataFrame() df['id'] = [1, 1, 1, 1, 1, 2, 2, 2,3, 3] df['val'] = [11, 10, 12, 3, 4, 5, 125, 45,31, -2] df['date'] = ['2019-03-31 06:00:00','2019-03-31 06:15:00', '2019-03-31 06:30:00', '2019-03-31 06:45:00', '2019-03-31 07:00:00', '2019-03-31 06:00:00', '2019-03-31 06:30:00', '2019-03-31 06:45:00', '2019-03-31 06:00:00', '2019-03-31 06:15:00']
测试数据特征:
- id=1 包含全部5个时间步
- id=2 缺失6:15、7:00两个时间步
- id=3 缺失6:30、6:45、7:00三个时间步
实现代码
方法1:通用版(适配多日期场景,自动补全全量时间步)
先为每个id补全所有固定时间步,缺失值自动填充NaN后再转宽表,逻辑稳定:
注意:如果数据包含多个不同日期,生成多重索引时把日期维度也加入from_product的参数列表即可适配。
# 1. 格式预处理 df['date'] = pd.to_datetime(df['date']) df['time_slot'] = df['date'].dt.strftime('%H:%M') # 提取时分作为时间步标识 fixed_time_slots = ['06:00', '06:15', '06:30', '06:45', '07:00'] # 固定时间步列表 # 2. 补全每个id的所有固定时间步 full_index = pd.MultiIndex.from_product( [df['id'].unique(), fixed_time_slots], names=['id', 'time_slot'] ) df_filled = df.set_index(['id', 'time_slot']).reindex(full_index).reset_index() # 3. 补全date列(若不需要保留date列可跳过此步) base_date = df['date'].dt.date.iloc[0] df_filled['date'] = pd.to_datetime(base_date.astype(str) + ' ' + df_filled['time_slot']) # 4. 长表转宽表 result = df_filled.pivot(index='id', columns='time_slot', values='val').reset_index() # 重命名列,方便识别 result.columns = ['id'] + [f'val_{slot}' for slot in fixed_time_slots]
运行后输出结果:
id val_06:00 val_06:15 val_06:30 val_06:45 val_07:00 0 1 11.0 10.0 12.0 3.0 4.0 1 2 5.0 NaN 125.0 45.0 NaN 2 3 31.0 -2.0 NaN NaN NaN
方法2:精简版(仅适配单日期场景)
如果确定所有数据属于同一日期,不需要补全date字段,可以直接透视后补全缺失列,代码更短:
df['date'] = pd.to_datetime(df['date']) df['time_slot'] = df['date'].dt.strftime('%H:%M') fixed_time_slots = ['06:00', '06:15', '06:30', '06:45', '07:00'] result = df.pivot(index='id', columns='time_slot', values='val') result = result.reindex(columns=fixed_time_slots).reset_index() result.columns = ['id'] + [f'val_{slot}' for slot in fixed_time_slots]
输出结果和方法1完全一致。
内容的提问来源于stack exchange,提问作者Sadcow
相关产品推荐
相关产品推荐

