如何在Python中为每个ID追加timestamp的并集并保留原数据?
为每个ID补全所有时间戳并插值填充value1
我有一个包含ID、timestamp、value1、gender和age五列的DataFrame,希望实现以下需求:
- 为每个ID追加所有ID的timestamp并集
- 保留原timestamp对应的value1、gender和age值
- 新增的timestamp对应的value1使用插值计算
之前尝试过按ID分组处理的自定义函数,但只能处理不同日期的情况,无法处理同一天内的不同时间值。
当前数据
| ID | value1 | timestamp | gender | age |
|---|---|---|---|---|
| 1 | 50 | 2022-01-01 12:00:00 | m | 7 |
| 1 | 80 | 2022-01-01 12:30:00 | m | 7 |
| 1 | 65 | 2022-01-01 13:00:00 | m | 7 |
| 2 | 65 | 2022-01-01 12:02:00 | f | 8 |
| 2 | 83 | 2022-01-01 12:22:00 | f | 8 |
| 2 | 63 | 2022-01-01 12:42:00 | f | 8 |
期望结果
| ID | value1 | timestamp | gender | age |
|---|---|---|---|---|
| 1 | 50 | 2022-01-01 12:00:00 | m | 7 |
| 1 | interpolated_value | 2022-01-01 12:02:00 | m | 7 |
| 1 | interpolated_value | 2022-01-01 12:22:00 | m | 7 |
| 1 | 80 | 2022-01-01 12:30:00 | m | 7 |
| 1 | interpolated_value | 2022-01-01 12:42:00 | m | 7 |
| 1 | 65 | 2022-01-01 13:00:00 | m | 7 |
| 2 | interpolated_value | 2022-01-01 12:00:00 | f | 8 |
| 2 | 65 | 2022-01-01 12:02:00 | f | 8 |
| 2 | 83 | 2022-01-01 12:22:00 | f | 8 |
| 2 | interpolated_value | 2022-01-01 12:30:00 | f | 8 |
| 2 | 63 | 2022-01-01 12:42:00 | f | 8 |
| 2 | interpolated_value | 2022-01-01 13:00:00 | f | 8 |
解决方案代码
import pandas as pd # 读取/创建当前数据 data = { 'ID': [1, 1, 1, 2, 2, 2], 'value1': [50, 80, 65, 65, 83, 63], 'timestamp': ['2022-01-01 12:00:00', '2022-01-01 12:30:00', '2022-01-01 13:00:00', '2022-01-01 12:02:00', '2022-01-01 12:22:00', '2022-01-01 12:42:00'], 'gender': ['m', 'm', 'm', 'f', 'f', 'f'], 'age': [7, 7, 7, 8, 8, 8] } df = pd.DataFrame(data) # 1. 将timestamp转换为datetime类型,确保时间排序正确 df['timestamp'] = pd.to_datetime(df['timestamp']) # 2. 获取所有ID的时间戳并集 all_timestamps = df['timestamp'].unique() # 3. 为每个ID生成包含所有时间戳的基础数据 # 先获取每个ID的唯一gender和age值(假设每个ID的gender/age唯一) id_attrs = df.groupby('ID')[['gender', 'age']].first().reset_index() # 生成ID和所有时间戳的笛卡尔积 full_timestamps = id_attrs.assign(key=1).merge(pd.DataFrame({'timestamp': all_timestamps, 'key': 1}), on='key').drop('key', axis=1) # 4. 合并原始数据,保留已有value1,缺失值标记为待插值 merged = full_timestamps.merge(df, on=['ID', 'timestamp', 'gender', 'age'], how='left') # 5. 按ID分组,对timestamp排序后进行线性插值 merged = merged.sort_values(['ID', 'timestamp']) merged['value1'] = merged.groupby('ID')['value1'].transform(lambda x: x.interpolate(method='time')) # 6. 重置索引并查看结果 result = merged.reset_index(drop=True) print(result)
步骤说明
- 时间类型转换:将
timestamp转为datetime类型,保证时间排序和插值的准确性。 - 获取全局时间戳:提取所有ID的时间戳并集,作为每个ID需要补全的时间点。
- 生成笛卡尔积:通过每个ID的属性(gender/age)与全局时间戳做笛卡尔积,得到每个ID需要的完整时间序列。
- 合并原始数据:将原始数据与完整时间序列合并,已有时间点保留原
value1,新增时间点留空。 - 时间插值:按ID分组后,使用
interpolate(method='time')基于时间间隔进行线性插值,自动计算新增时间点的value1。 - 整理结果:排序并重置索引,得到最终符合要求的DataFrame。
内容的提问来源于stack exchange,提问作者dspractician
相关产品推荐
相关产品推荐

