Pandas跨时间戳多组行前向填充高效方案求助
高效实现Pandas跨时间戳多组行前向填充
需要实现的需求:将同一时间戳下的多个非NaN Name 作为一组,前向传播填充到后续所有时间戳行中,直到下一组非NaN Name 出现。现有循环实现处理10万行数据时效率低下,需高效解决方案。
输入数据
import pandas as pd import numpy as np df = pd.DataFrame({ 'Timestamp': [ pd.Timestamp('19/01/2022 10:00:00'), pd.Timestamp('19/01/2022 10:00:00'), pd.Timestamp('19/01/2022 15:00:00'), pd.Timestamp('19/01/2022 15:30:00'), pd.Timestamp('19/01/2022 16:00:00'), pd.Timestamp('19/01/2022 19:30:00'), pd.Timestamp('19/01/2022 20:00:00'), pd.Timestamp('19/01/2022 20:30:00'), pd.Timestamp('20/01/2022 13:00:00'), pd.Timestamp('20/01/2022 13:30:00'), pd.Timestamp('20/01/2022 14:00:00'), pd.Timestamp('20/01/2022 14:50:00'), pd.Timestamp('20/01/2022 15:00:00')], 'Name': [ 'A', 'B', np.NaN, np.NaN, np.NaN, 'C', np.NaN, np.NaN, np.NaN, np.NaN, np.NaN, 'D', np.NaN]})
期望输出
desired_output = pd.DataFrame({ 'Timestamp': [ pd.Timestamp('19/01/2022 10:00:00'), pd.Timestamp('19/01/2022 10:00:00'), pd.Timestamp('19/01/2022 15:00:00'), pd.Timestamp('19/01/2022 15:00:00'), pd.Timestamp('19/01/2022 15:30:00'), pd.Timestamp('19/01/2022 15:30:00'), pd.Timestamp('19/01/2022 16:00:00'), pd.Timestamp('19/01/2022 16:00:00'), pd.Timestamp('19/01/2022 19:30:00'), pd.Timestamp('19/01/2022 20:00:00'), pd.Timestamp('19/01/2022 20:30:00'), pd.Timestamp('20/01/2022 13:00:00'), pd.Timestamp('20/01/2022 13:30:00'), pd.Timestamp('20/01/2022 14:00:00'), pd.Timestamp('20/01/2022 14:50:00'), pd.Timestamp('20/01/2022 15:00:00')], 'Name': [ 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B', 'C', 'C', 'C', 'C', 'C', 'C', 'D', 'D']})
现有低效循环实现
import time t0 = time.time() unique_timestamps = df.Timestamp.unique() new_entries = [] last_valid = None for ut in unique_timestamps: val = df[df.Timestamp == ut]['Name'].values if isinstance(val[0], float) and np.isnan(val[0]) and last_valid is not None: new_entries.append(pd.DataFrame({'Timestamp': ut, 'Name': last_valid})) else: last_valid = df[df.Timestamp == ut]['Name'] output = pd.concat([df, pd.concat(new_entries)]).dropna().sort_values('Timestamp') t1 = time.time() print(f"耗时:{t1-t0}s")
高效矢量化解决方案
利用Pandas的分组、聚合和映射操作实现全矢量化处理,避免循环,大幅提升处理效率:
# 1. 按Timestamp分组,提取每个时间戳的非NaN Name列表 grouped = df.groupby('Timestamp')['Name'].agg(lambda x: x.dropna().tolist()) # 2. 创建填充组标识:遇到非空Name列表时生成新组,否则继承上一组的标识 group_key = (grouped.str.len() > 0).cumsum() # 3. 提取每个组对应的Name列表,用组标识映射实现前向填充 name_mapping = grouped[grouped.str.len() > 0] filled_names = group_key.map(name_mapping) # 4. 将每个时间戳的Name列表展开为多行,得到最终结果 result = filled_names.explode().reset_index() # 验证结果是否匹配期望输出(无输出则表示完全匹配) print(pd.testing.assert_frame_equal(result, desired_output, check_dtype=False))
方案优势
- 全程使用Pandas底层优化的矢量化操作,避免Python循环的性能开销
- 处理10万行级数据时,效率比循环实现提升数倍甚至数十倍
- 代码简洁逻辑清晰,易于维护和扩展
内容的提问来源于stack exchange,提问作者gamma2023
相关产品推荐
相关产品推荐

