Pandas时间索引数据如何检测值上升-持平-再上升模式并标记输出1/0
实现代码与逻辑说明
核心逻辑
- 首先识别连续持平的平台期:使用连续相同值分组方法,不会打乱原有时间序列顺序,仅保留连续长度≥2的组作为有效平台期
- 校验平台期前后的上升条件:平台期起始前最后一个数值 < 平台期数值(满足首次上升),平台期结束后第一个数值 > 平台期数值(满足二次上升)
- 符合条件的在平台期结束后第一行标记1,其余位置标记0
完整可运行代码
import pandas as pd import numpy as np def mark_pattern(df, value_cols=None, min_plateau_len=2): """ 参数说明: df: 输入按时间排序的DataFrame value_cols: 待检测的数值列列表,不传则默认自动使用所有数值类型列 min_plateau_len: 最小平台期长度,默认2,可自定义为你需要的x值 """ df = df.copy() # 自动识别数值列作为待处理列 if value_cols is None: value_cols = df.select_dtypes(include=np.number).columns.tolist() # 初始化输出列全为0 df['desired output'] = 0 for col in value_cols: # 给连续相同值打分组ID,完全保留原有顺序,无排序操作 equal_group = df[col].ne(df[col].shift()).cumsum() # 计算每个分组的长度 group_len = equal_group.map(equal_group.value_counts()) # 筛选出长度符合要求的平台期分组 valid_plateaus = equal_group[group_len >= min_plateau_len].unique() for g in valid_plateaus: g_mask = equal_group == g # 平台期数值 plateau_val = df.loc[g_mask, col].iloc[0] # 平台期起始前一行的位置 pre_idx = df[g_mask].index[0] - 1 # 平台期结束后一行的位置 post_idx = df[g_mask].index[-1] + 1 # 检查前后索引是否合法,以及上升条件是否满足 if pre_idx in df.index and post_idx in df.index: pre_val = df.loc[pre_idx, col] post_val = df.loc[post_idx, col] if pre_val < plateau_val and post_val > plateau_val: df.loc[post_idx, 'desired output'] = 1 return df # 调用示例 # df = pd.read_csv('你的csv路径.csv') # 若你的时间列是字符串格式先转成时间类型再按时间排序(你已经是排好序的可以跳过排序步骤) # df['time'] = pd.to_datetime(df['time']) # df = df.sort_values('time').reset_index(drop=True) # result_df = mark_pattern(df)
注意事项
- 若你的数值为浮点数,存在精度误差时,可以先对数值列做精度对齐,比如
df[value_cols] = df[value_cols].round(3),再传入函数进行判断,避免因浮点精度问题漏判持平场景 - 支持多列数值同时检测,只要任意一列符合模式就会标记为1,你可以根据需求调整多列的判断逻辑(比如要求所有列都符合才标记)
- 完全基于行顺序计算,无任何打乱时间序列的排序操作,符合时间序列处理要求
内容的提问来源于stack exchange,提问作者Garrad2810
相关产品推荐
相关产品推荐

