如何在DataFrame中按日筛选满足前置行条件的第3行并生成sig列
问题
需要为大型DataFrame新增一列值为0或1的sig列,规则如下:
- 仅针对每日08:30开始的第3行进行判断:若该行
data值 > 上一行data值 > 上上行data值,则sig设为1,否则为0; - 其余所有行的
sig值固定为0; - 限制:原始DataFrame的时间戳秒间隔不固定,无法通过时间间隔判断行位置,且每日的总行数不固定。
示例DataFrame
import pandas as pd import numpy as np pd.set_option('display.max_rows', 500) np.random.seed(100) dates = pd.date_range("2022.01.01", "2022.01.31", freq="s") dates=dates[:-1] df = pd.DataFrame({'date':dates, 'data':np.random.randint(low=0, high=100, size=len(dates)).tolist()}) df['_date'] = pd.to_datetime(df['date']) df.set_index('date', inplace=True) df = df.loc[(df._date.dt.hour == 8) & (df._date.dt.minute == 30) & ((df._date.dt.second >= 0) & (df._date.dt.second <= 10))].head(30) df.drop(['_date'], axis=1, inplace=True)
示例输出(处理前):
data date 2022-01-01 08:30:00 14 2022-01-01 08:30:01 27 2022-01-01 08:30:02 33 2022-01-01 08:30:03 77 2022-01-01 08:30:04 66 2022-01-01 08:30:05 60 2022-01-01 08:30:06 72 2022-01-01 08:30:07 21 2022-01-01 08:30:08 70 2022-01-01 08:30:09 60 2022-01-01 08:30:10 76 2022-01-02 08:30:00 13 2022-01-02 08:30:01 73 2022-01-02 08:30:02 71 2022-01-02 08:30:03 78 2022-01-02 08:30:04 50 2022-01-02 08:30:05 80 2022-01-02 08:30:06 48 2022-01-02 08:30:07 24 2022-01-02 08:30:08 29 2022-01-02 08:30:09 43 2022-01-02 08:30:10 75 2022-01-03 08:30:00 11 2022-01-03 08:30:01 52
期望结果
data sig date 2022-01-01 08:30:00 14 0 2022-01-01 08:30:01 27 0 2022-01-01 08:30:02 33 1 2022-01-01 08:30:03 77 0 2022-01-01 08:30:04 66 0 2022-01-01 08:30:05 60 0 2022-01-01 08:30:06 72 0 2022-01-01 08:30:07 21 0 2022-01-01 08:30:08 70 0 2022-01-01 08:30:09 60 0 2022-01-01 08:30:10 76 0 2022-01-02 08:30:00 13 0 2022-01-02 08:30:01 73 0 2022-01-02 08:30:02 71 0 2022-01-02 08:30:03 78 0 2022-01-02 08:30:04 50 0 2022-01-02 08:30:05 80 0 2022-01-02 08:30:06 48 0 2022-01-02 08:30:07 24 0 2022-01-02 08:30:08 29 0 2022-01-02 08:30:09 43 0 2022-01-02 08:30:10 75 0 2022-01-03 08:30:00 11 0 2022-01-03 08:30:01 32 0 2022-01-03 08:30:02 52 1 2022-01-03 08:30:03 44 0 2022-01-03 08:30:03 75 0
解决方案
通过按日期分组+组内排序+行号标记+条件判断的方式实现,代码如下:
# 核心处理逻辑 # 1. 提取日期部分,用于按自然日分组 df['day'] = df.index.date # 2. 按日期分组,组内按时间排序(确保顺序正确),并为每行分配组内行号(从0开始计数) df['row_num'] = df.groupby('day').cumcount() # 3. 初始化sig列为0 df['sig'] = 0 # 4. 筛选每组的第3行(row_num=2),判断连续三行的data递增关系,满足条件则设为1 mask = (df['row_num'] == 2) & \ (df['data'] > df.groupby('day')['data'].shift(1)) & \ (df.groupby('day')['data'].shift(1) > df.groupby('day')['data'].shift(2)) df.loc[mask, 'sig'] = 1 # 可选:删除中间辅助列 df.drop(['day', 'row_num'], axis=1, inplace=True) # 查看结果 print(df)
关键逻辑说明
df.index.date:从时间戳索引中提取纯日期,确保同一自然日的行被分到同一组;groupby('day').cumcount():为每组内的行按时间顺序分配行号,完美适配每日行数不固定的场景;shift(1)/shift(2):在组内获取当前行的前1行、前2行data值,实现连续三行的递增判断;- 仅对
row_num=2的行应用条件判断,其余行保持sig=0,完全符合需求。
内容的提问来源于stack exchange,提问作者stanvooz
相关产品推荐
相关产品推荐

