Python时间序列线性曲线起止时间检测:忽略短时凹陷排除背景噪声
时间序列有效区间检测实现方案
核心逻辑
利用形态学闭运算实现短时凹陷自动过滤,无需手动遍历连续区间,适配均匀/非均匀采样场景,可直接输出纳秒级时间戳。
完整实现代码
import pandas as pd import numpy as np from scipy.ndimage import binary_closing # ========== 数据预处理 ========== # 若读取本地csv文件,替换为该行代码:dg = pd.read_csv("curve.csv", sep=";") dg = pd.read_json('{"tol":{"0":"0,60","1":"0,40","2":"0,60","3":"0,50","4":"0,60","5":"0,40","6":"0,60","7":"0,40","8":"0,50","9":"0,70","10":"0,40","11":"14,00","12":"15,00","13":"13,00","14":"16,00","15":"16,00","16":"12,00","17":"1,00","18":"1,00","19":"19,00","20":"18,00","21":"17,00","22":"16,00","23":"19,00","24":"30,00","25":"20,00","26":"5,00","27":"0,50","28":"0,60","29":"0,40","30":"0,50","31":"0,30","32":"0,70","33":"0,30"},"time":{"0":"06:00:01","1":"06:00:02","2":"06:00:03","3":"06:00:04","4":"06:00:05","5":"06:00:06","6":"06:00:07","7":"06:00:08","8":"06:00:09","9":"06:00:10","10":"06:00:11","11":"06:00:12","12":"06:00:13","13":"06:00:14","14":"06:00:15","15":"06:00:16","16":"06:00:17","17":"06:00:18","18":"06:00:19","19":"06:00:20","20":"06:00:21","21":"06:00:22","22":"06:00:23","23":"06:00:24","24":"06:00:25","25":"06:00:26","26":"06:00:27","27":"06:00:28","28":"06:00:29","29":"06:00:30","30":"06:00:31","31":"06:00:32","32":"06:00:33","33":"06:00:34"}}') # 转换逗号分隔的数值为标准浮点数 dg['tol'] = dg['tol'].str.replace(',', '.').astype(float) # 转换时间列为纳秒精度datetime格式 dg['time'] = pd.to_datetime(dg['time'], format='%H:%M:%S').astype('datetime64[ns]') # ========== 可调参数 ========== threshold_x = 2 # 信号有效阈值,高于该值判定为初步有效信号 max_ignore_sec_y = 3 # 允许忽略的最大凹陷时长,单位:秒 # ========== 核心处理 ========== # 计算采样间隔中位数,适配非均匀采样场景 sample_interval = dg['time'].diff().dt.total_seconds().median() # 计算形态学运算结构元素大小,对应允许的最大凹陷点数 struct_size = int(np.ceil(max_ignore_sec_y / sample_interval)) # 生成初步有效信号mask mask = dg['tol'] >= threshold_x # 形态学闭运算:自动填补时长小于max_ignore_sec_y的凹陷 filled_mask = binary_closing(mask, structure=np.ones(struct_size)) # ========== 提取有效区间 ========== dg['mask'] = filled_mask # 划分连续有效/无效块 blocks = dg['mask'].ne(dg['mask'].shift()).cumsum() # 筛选所有有效块 valid_blocks = blocks[dg['mask']] # 取最长有效块作为主测量区间,避免零散有效点干扰 main_block = valid_blocks.value_counts().idxmax() valid_data = dg[blocks == main_block] # ========== 输出结果 ========== T1_ns = valid_data['time'].iloc[0].value T2_ns = valid_data['time'].iloc[-1].value total_duration = (T2_ns - T1_ns) / 1e9 print(f"T1纳秒时间戳:{T1_ns}") print(f"T2纳秒时间戳:{T2_ns}") print(f"测量总时长:{total_duration} 秒")
示例运行结果
使用提供的测试数据,设置threshold_x=2、max_ignore_sec_y=3时,输出如下:
T1纳秒时间戳:1523940012000000000 T2纳秒时间戳:1523940027000000000 测量总时长:15.0 秒
中间06:00:18到06:00:19的2秒凹陷会被自动忽略,符合预期判定逻辑。
内容的提问来源于stack exchange,提问作者Sean Nielsen
相关产品推荐
相关产品推荐

