Pandas如何新增列显示某特定值在列中的上一次出现对应值
Pandas 实现「记录上一次状态为On的时间」的几种方案
最常用、性能最好的实现方式有以下3种,按推荐优先级排序:
- 方法1:
where+ 前向填充ffill(优先推荐)
核心逻辑:先把所有status不等于On的行的时间值置为空值,对整列做前向填充,最后把On行自身对应的填充值下移一位,就能得到上一次On的时间。
import pandas as pd import numpy as np # 构造示例DataFrame df = pd.DataFrame({ 'time': ['10:00','10:01','10:02','10:03','10:04','10:05','10:06','10:07','10:08','10:09','10:10'], 'status': ['On','Off','Off','Off','On','Off','Off','Off','Off','On','Off'] }) # 计算last_on列 df['last_on'] = df['time'].where(df['status'] == 'On').ffill() # 修正On行的取值:取上一个On的时间,而非当前行时间 df.loc[df['status'] == 'On', 'last_on'] = df.loc[df['status'] == 'On', 'last_on'].shift(1)
运行后输出和你给出的预期结果完全一致,该方法为pandas原生向量化运算,百万行级数据也能秒出结果。
- 方法2:累计计数分组映射
核心逻辑:每遇到一次status == 'On'就给分组编号+1,每个分组对应两次On之间的所有记录,直接映射上一个分组的On时间即可。
# 生成分组标记 df['group_tag'] = (df['status'] == 'On').cumsum() # 提取每个分组对应的On时间 on_time_dict = df.query("status == 'On'").set_index('group_tag')['time'].to_dict() # 映射上一组的On时间,没有上一组则返回NaN df['last_on'] = df['group_tag'].map(lambda x: on_time_dict.get(x-1, np.nan)) # 删除临时分组列 df.drop(columns='group_tag', inplace=True)
该方法逻辑直观易理解,性能接近方法1,适合pandas新手梳理逻辑使用。
- 方法3:逐行迭代(仅推荐小数据量场景)
核心逻辑:遍历所有行,用一个临时变量实时保存最近一次遇到的On时间,逐行给新列赋值,遇到新的On时更新临时变量。
last_on = np.nan res = [] for status, current_time in zip(df['status'], df['time']): res.append(last_on) if status == 'On': last_on = current_time df['last_on'] = res
该写法不需要记忆复杂的pandas API,逻辑最直白,但pandas迭代效率低,数据量超过10万行时运行速度会明显下降,不适合大数据场景。
提示:如果你的
time列已经是datetime类型而非字符串,上述所有方法都可以直接运行,不需要额外做类型转换。
内容的提问来源于stack exchange,提问作者Jorge Ramos
相关产品推荐
相关产品推荐

